Django进阶--表单-模型表单

Django进阶–表单-模型表单

django版本:2.7.1

python版本:3.6

1. 简介

项目开发中,一个数据库模型通常需要有紧密关联的表单。举个栗子学生管理系统中:模型Student在前端页面中数据的增、改、查需要对应的表单。Django提供模型表单(ModelForm)将表单宇对应的模型紧密关联,使得代码更加灵活且维护方便。

2. 使用

2.1 流程

1. 创建模型表单类
from django import forms
class StudentForm(forms.ModelForm):
    class Meta:
        model = Student
        exclude = ['is_deleted'] #列表中的值是Student模型类的字段

class DetailForm(forms.ModelForm):
    class Meta:
        model = StuDetail
        exclude = ['student']  #表示除去【'student'】字段外,Student模型类中声明的其他字段都将添加进DetailForm
        #上式 <=> fields = ['qq', 'email'] fields关键字表示取出
  • 需要继承forms.ModelForm
  • 设置元类Meta,在里面声明需要的模型字段;
  • 相对于模型字段集合, ecclude表示除去,fields表示取出。

2. 字段类型

取自: 官方文档

模型领域 表格字段
AutoField 没有在表格中表示
BigAutoField 没有在表格中表示
CharField CharField
DateField DateField
DateTimeField DateTimeField
EmailField EmailField
ForeignKey ModelChoiceField
ManyToManyField ModelMultipleChoiceField
FileField FileField
TextField CharField,并带有widget=forms.Textarea参数
  • Model字段和表单字段有大量相似之处
  • ForeignKey被映射成为表单类的django.forms.ModelChoiceField,它的选项是一个模型的QuerySet,也就是可以选择的对象的列表,但是只能选择一个。
  • ManyToManyField被映射成为表单类的django.forms.ModelMultipleChoiceField,它的选项也是一个模型的QuerySet,也就是可以选择的对象的列表,但是可以同时选择多个,多对多嘛。

对于各别字段详解:

  • 如果模型字段设置blank=True,那么表单字段的required设置为False。 否则,required=True。
  • 表单字段的label属性根据模型字段的verbose_name属性设置,并将第一个字母大写。
  • 如果模型的某个字段设置了editable=False属性,那么它表单类中将不会出现该字段。道理很简单,都不能编辑了,还放在表单里提交什么?
  • 表单字段的help_text设置为模型字段的help_text
  • 如果模型字段设置了choices参数,那么表单字段的widget属性将设置成Select框,其选项来自模型字段的choices。选单中通常会包含一个空选项,并且作为默认选择。如果该字段是必选的,它会强制用户选择一个选项。 如果模型字段具有default参数,则不会添加空选项到选单中。

2.2 后台使用

from .models import Student, StuDetail
from .forms import RegisterForm, StudentForm, DetailForm

def new_edit(request, pk):		#模型Student和StuDetail是一对一关系
    stu = Student.objects.get(pk=pk)     		
    stu_form = StudentForm(instance=stu)		#填充表单
    try:
        detail_form = DetailForm(instance=stu.studetail)
    except:
        studetail = StuDetail()
        stu.studetail = studetail
        studetail.save()
        detail_form = DetailForm(instance=studetail)

    if request.method == 'POST':
        stu_form = StudentForm(request.POST)    #不指定instance将用data=request.POST填充表单
        detail_form = DetailForm(request.POST)
    context = {
        'section': '学生信息修改',
        'stu_form': stu_form,
        'detail_form': detail_form,
        'stu': stu,
    }
    return render(request, 'book/stu_newedit.html', context=context)

  • instance:指明填充实例。
  • 若要将表单内数据存入数据库,可直接使用model_form(即表单对象)的save()方法,会利用对性的模型类将数据刷入数据库。例如上例中:detail_form.save()

2.3 前端调用

{% load myfilters %}
    
{% csrf_token %} {% for field in stu_form %} <div class="form-group "> <label class="control-label">{{ field.errors }}label> <label class="col-sm-2 control-label">{{ field.label }}label> <div class="col-sm-3 "> {{ field|addclass:'form-control' }} div> div> {% endfor %} <div style="margin-left: 25%"> <button type="submit" class="btn btn-primary btn-lg active">提交button> div> form> {% endblock %}
  • 欲给field添加class(用于添加css样式),可使用过滤器或标签等
@register.filter(name='addclass')
def form_add_class(self, class_name):
    return self.as_widget(attrs={'class':class_name})
  • field.as_widget(attrs={属性名:属性值}),添加后该field对应的标签会添加class属性

3. 自定义验证

仅验证字段的合理性(field.clean)

3.1 模型

# models.py
class StuDetail(models.Model):
    qq = models.CharField('QQ号码', max_length=20, unique=True, default='', error_messages={'unique': 'QQ号码重复'})   # 添加错误信息
    phone = models.CharField('联系电话', max_length=20, unique=True, default='')
    student = models.OneToOneField(Student, on_delete=models.CASCADE)


3.2 验证

#views.py
def new_edit(request, pk):
    stu = Student.objects.get(pk=pk)

    if request.method == 'POST':
        stu_form = StudentForm(request.POST, instance=stu)
        detail_form = DetailForm(request.POST, instance=stu.studetail)
        if stu_form.is_valid() & detail_form.is_valid():
            stu_form.save()
            detail_form.save()
            return redirect(reverse('book:students'))
    else:
        stu_form = StudentForm(instance=stu)
        try:
            detail_form = DetailForm(instance=stu.studetail)
        except:
            studetail = StuDetail()
            stu.studetail = studetail
            studetail.save()
            detail_form = DetailForm(instance=studetail)

    context = {
        'section': '学生信息修改',
        'stu_form': stu_form,
        'detail_form': detail_form,
        'stu': stu,
        # 'colleges': colleges,
    }

    return render(request, 'book/stu_newedit.html', context=context)

3.3 结果

前端使用2.3展示的界面

Django进阶--表单-模型表单_第1张图片


你可能感兴趣的:(Django,Django,模型表单)