Django11-ModelForm

1、定義ModelForm類

# 建立部門表單校驗html

class DepartmentForm(forms.ModelForm): 
    class Meta:
        model = models.Department    #關聯到Models中的表名Department
        fields = '__all__'      #獲取Department表中的全部對象,也能夠寫成列表['depName','depDes'],指定要獲取的對象,並且是有順序的
        labels = {
            'depName': '部門名稱',
            'depDes': '職責描述',
        }
        widgets = {         #設置插件,type類型和類名等屬性 
            'depName': forms.TextInput(attrs={'class': 'form-control','placeholder':'請輸入部門名稱'}),
            'depDes': forms.TextInput(attrs={'class': 'form-control','placeholder':'請輸入部門職責描述'}),
        }

class Meta:下經常使用參數:前端

model = models.Department    # 對應的Model中的類
fields = "__all__"            # 字段,若是是__all__,就是表示列出全部的字段,也能夠寫成列表['title','price'],指定要獲取的對象
exclude = None             # 排除的字段
labels = None                # 提示信息
help_texts = None              # 幫助提示信息
widgets = None             # 自定義插件,form組件裏是widget,ModelForm組件裏是widgets
error_messages = None         # 自定義錯誤信息django

其中label屬性能夠不在ModelForm這裏面寫,也能夠在models.py中的Depart表中各個對象定義verbose_name屬性值,用於非ForeignKey對象,
推薦這種寫法,在Admin系統中也能夠顯示這裏定義的verbose_name值bootstrap

class Depart(models.Model):
    depName = models.TextField(max_length=32, verbose_name='部門名稱')
    depDes = models.TextField(max_length=64, black=True, null=True, verbose_name='職責描述')

2、批量添加樣式

可經過重寫ModelForm類的init方法來實現。ide

# 建立部門表單校驗函數

class DepartmentForm(forms.ModelForm):
    depName = forms.TextField(validators=[],)   #若是depName字段存在,就表明重寫這個字段
    count = forms.TextField(validators=[],)     #若是count字段不存在,就表明新增這個字段,models文件中不存在這個字段
    class Meta:
        model = models.Department   #model和fields都是固定寫法,不能寫
        fields = '__all__'
        labels = {
            'depName': '部門名稱',
            'depDes': '職責描述',
        }
        widgets = {
            'depName': forms.TextInput(attrs={'placeholder':'請輸入部門名稱'}),
            'depDes': forms.TextInput(attrs={'placeholder':'請輸入部門職責描述'}),
             'purchase_date': forms.widgets.DateInput(attrs={'type': 'date'}),
                 'expiration_date': forms.widgets.DateInput(attrs={'type': 'date'}),

        }
        error_messages = {      #這裏的error_messages只能寫默認存在的校驗字段
            'depName':{
                'required':'不能爲空'
            }
        }
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        for field in self.fields.values():
            field.widget.attrs.update({'class': 'form-control'})


class DepartAdd(View):
    def get(self, request):
        form_obj = DepartmentForm()
        return render(request, 'departadd.html', {'form_obj': form_obj})
    
    def post(self, request):
        form_obj = DepartmentForm(request.POST)
        print(form_obj)
        if form_obj.is_valid():
            # models.Department.objects.create(**form_obj.cleaned_data)
            form_obj.save()        #直接save()方法就能夠保存     
            return redirect(reverse('departList'))

3、部門添加、修改例子(FVB版)

部門添加oop

def depart_add(request):
    form_obj = departForm.DepartForm()
    if request.method == 'POST':
        form_obj = departForm.DepartForm(request.POST)
        if form_obj.is_valid():
            form_obj.save()
            return redirect(reverse('depart_list'))
    return render(request, 'depart/depart_add.html', {'form_obj': form_obj})

部門修改post

def depart_edit(request, pk):
    form_edit = models.Depart.objects.filter(pk=pk).first()
    form_obj = departForm.DepartForm(instance=form_edit)
    if request.method == 'POST':
        form_obj = departForm.DepartForm(request.POST, instance=form_edit)   #這裏要將當前對象做爲一個實例傳給ModelForm  
        # 若是沒有修改,則不須要校驗
        depart_name_new = request.POST.get('depart_name', None)
        if form_edit.depart_name == depart_name_new:
            # 部門描述不須要校驗,直接更新保存
            form_edit.depart_desc = request.POST.get('depart_desc', None)
            form_edit.save()
            return redirect(reverse('depart_list'))
        # 若是修改了值,就調用DepartForm校驗,注意用instance表示將當前對象傳給Modelform校驗,模板中字段仍然能夠自動生成
        elif form_obj.is_valid():
            form_obj.save()
            return redirect(reverse('depart_list'))
    return render(request, 'depart/depart_edit.html', {'form_edit': form_edit, 'form_obj': form_obj})

前端頁面ui

展現頁面depart_list.htmlurl

<table class="form-horizontal table table-bordered" style="margin-top: 10px">
    <thead>
    <tr>
        <th>ID</th>
        <th>用戶名稱</th>
        <th>密碼</th>
        <th>所屬部門</th>
        <th>操做</th>
    </tr>
    </thead>
    <tbody>
    {% for user in user_all %}
        <tr>
        <td>{{ forloop.counter }}</td>
        <td>{{ user.username }}</td>
        <td>{{ user.pwd }}</td>
{#        <td>{{ user.depart.depart_name}}</td>#}  #這裏能夠經過depart外鍵.depart_name來獲取部門名稱進行前端頁面顯示
         <td>{{ user.depart }}</td>                         #也能夠經過在models.py中給Depart類寫__str__方法,這裏就不須要用點方法了
        <td>
            <a href="{% url 'user_edit' user.pk %}"><i class="fa fa-edit fa-2x"></i></a>&nbsp;&nbsp;&nbsp;&nbsp;
            <a class="del" del_obj="user" del_id="{{ user.pk }}"><i class="fa fa-trash-o fa-2x" style="cursor: pointer;"></i></a>
        </td>
        </tr>
    {% endfor %}
    </tbody>
</table>

修改頁面depart_edit.html

<form action="" method="post" class="form-horizontal">
    {% csrf_token %}
    <div class="form-group {% if form_obj.depName.errors %}has-error{% endif %}">
        <label for="{{ form_obj.depName.id_for_label }}" class="col-lg-2 control-label">{{ form_obj.depName.label }}</label>
        <div class="col-lg-6">
            {{ form_obj.depName }}
        </div>
        <span class="help-block">{{ form_obj.errors.0 }}</span>
    </div>

bootstrape樣式中使用has-error和help-block類渲染錯誤提示效果

models.py

from django.db import models

# Create your models here.
class Depart(models.Model):
    depart_name = models.CharField(max_length=32, verbose_name='部門名稱')
    depart_desc = models.CharField(max_length=64, verbose_name='部門描述')
    
        #經過寫__str__方法,前端直接調用depart對象時就能夠直接獲取到depart_name的值了
    def __str__(self):
        return self.depart_name

class User(models.Model):
    username = models.CharField(max_length=32, verbose_name='用戶名')
    pwd = models.CharField(max_length=32, verbose_name='密碼')
    depart = models.ForeignKey(to='Depart', verbose_name='所屬部門')

4、代碼合併

一、depart_all.html模板代碼合併

未合併寫法,寫了多個form-group,重複

<form action="" method="post" class="form-horizontal" novalidate>
    {% csrf_token %}
    <div class="form-group {% if form_obj.depart_name.errors %}has-error{% endif %}">
        <label for="{{ form_obj.depart_name.id_for_label }}" class="col-lg-2 control-label">
            {{ form_obj.depart_name.label }}
        </label>
        <div class="col-lg-6">
            {{ form_obj.depart_name }}
            <span class="help-block">{{ form_obj.depart_name.errors.0 }}</span>
        </div>
    </div>

    <div class="form-group {% if form_obj.depart_desc.errors %}has-error{% endif %}">
        <label for="{{ form_obj.depart_desc.id_for_label}}" class="col-lg-2 control-label ">
            {{ form_obj.depart_desc.label }}
        </label>
        <div class="col-lg-6">
            {{ form_obj.depart_desc }}
            <span class="help-block">{{ form_obj.depart_desc.errors.0 }}</span>
        </div>
    </div>

    <div class="form-group">
        <div class="col-lg-10 col-lg-offset-2">
            <button class="btn btn-primary">提交</button>
        </div>
    </div>
</form>
View Code

合併寫法

<form action="" method="post" class="form-horizontal" novalidate>
    {% csrf_token %}

    {#須要渲染多個form-group, 可使用for循環避免從新編寫,將form_obj.depart_name和form_obj.depart_desc改爲field便可#}
    {% for field in form_obj %}
    <div class="form-group {% if field.errors %}has-error{% endif %}">
        <label for="{{ field.id_for_label }}" class="col-lg-2 control-label">
            {{ field.label }}
        </label>
        <div class="col-lg-6">
            {{ field }}
            <span class="help-block">{{ field.errors.0 }}</span>
        </div>
    </div>
    {% endfor %}

    <div class="form-group">
        <div class="col-lg-10 col-lg-offset-2">
            <button class="btn btn-primary">提交</button>
        </div>
    </div>
</form>
View Code

二、views.py視圖代碼合併

未合併寫法

urls.py
url(r'^user/add/$', user.user_add, name='user_add'),
url(r'^user/edit/(\d+)/$', user.user_edit, name='user_edit'),

views.py
#用戶添加函數
def user_add(request):
    form_obj = userForm.UserForm()
    if request.method == 'POST':
        form_obj = userForm.UserForm(request.POST)
        if form_obj.is_valid():
            form_obj.save()
            return redirect(reverse('user_list'))
    return render(request, 'user/user_add.html', {'form_obj': form_obj})

#用戶編輯函數
def user_edit(request, pk):
    obj = models.User.objects.filter(pk=pk).first()
    form_obj = userForm.UserForm(instance=obj)
    if request.method == 'POST':
        form_obj = userForm.UserForm(request.POST, instance=obj)
        # 若是未修改原值,則不校驗
        if request.POST.get('username', None) == obj.username:
            obj.pwd = request.POST.get('pwd', None)
            obj.gender = request.POST.get('gender', None)
            # depart不能直接保存爲request.POST.get('depart',None),由於depart是一個外鍵,須要保存Depart的一個實例
            obj.depart = models.Depart.objects.filter(pk=request.POST.get('depart', None)).first()
            obj.save()
            # 這裏先建立用戶的時候校驗密碼不能爲空,可是修改用戶時沒有校驗密碼是否爲空
            return redirect(reverse('user_list'))
        # 修改了原值,則進行校驗
        elif form_obj.is_valid():
            form_obj.save()
            return redirect(reverse('user_list'))
    return render(request, 'user/user_edit.html', {'form_obj': form_obj})
View Code

將用戶添加函數和用戶編輯函數合併編寫

將urls中函數方法統一寫成user_change,在views中只須要寫一個user_change函數包含用戶添加和編輯功能。

urls.py
url(r'^user/add/$', user.user_change, name='user_add'),
url(r'^user/edit/(\d+)/$', user.user_change, name='user_edit'),

views.py
因爲用戶添加和編輯函數邏輯類似,能夠合併編寫
區別就是編輯函數須要傳入pk值,而添加函數不須要傳入pk值,因此設置pk=None默認爲空
其餘代碼基本相同

def user_change(request, pk=None):
        #若是是添加方法,則obj爲空
    obj = models.User.objects.filter(pk=pk).first()
    form_obj = userForm.UserForm(instance=obj)
    if request.method == 'POST':
        form_obj = userForm.UserForm(request.POST, instance=obj)
        if obj:
            # 若是未修改username原值,則不校驗
            if request.POST.get('username', None) == obj.username:
                obj.pwd = Md5(request.POST.get('pwd', None)).md5
                obj.gender = request.POST.get('gender', None)
                # depart不能直接保存爲request.POST.get('depart',None),由於depart是一個外鍵,須要保存Depart的一個實例
                obj.depart = models.Depart.objects.filter(pk=request.POST.get('depart', None)).first()
                obj.save()
                # 這裏先建立用戶的時候校驗密碼不能爲空,可是修改用戶時沒有校驗密碼是否爲空
                return redirect(reverse('user_list'))
        # 修改了原值,則進行校驗
        elif form_obj.is_valid():
            form_obj.save()
            return redirect(reverse('user_list'))
    return render(request, 'user/user_edit.html', {'form_obj': form_obj})
View Code
相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息