一. Forms组件补充

1.__init__()

如果继承forms.Form的类中的每一个字段,或者大部分字段都做了相同的约束,可以将该约束放到__init__中编写

实例:每一个字段都需要添加form-control类名

class BookForm(forms.Form):
    title = forms.CharField(max_length=32)
    pub_date = forms.DateField()
    price = forms.DecimalField(max_digits=8, decimal_places=2)

    def __init__(self,*args,**kwargs):
        super().__init__(*args,**kwargs)
        for field in self.fields.values():
            field.widget.attrs.update({"class":"form-control"})

2.ChoiceField属性,下拉菜单(元组套元组的形式)

(1)choices作用:在数据库中用元组的第一项作为存储的值,在显示时,将元组的第二项作为显示的内容,便于前端使用下拉框

例:

class Book(models.Model):
      id=models.AutoField(primary_key=True)
      title=models.CharField(max_length=32)
      gender=models.IntegerField(choices=((1,"男"),(2,"女")),default=1)

(2)与get_gender_display()方法同时使用,用来获取元组第二项的内容

(3)在forms组件中渲染时,只需将类型改变成ChoiceField()

例:

class BookForm(forms.Form):
      title = forms.CharField(label="书名",max_length=32)
      pub_date = forms.DateField(label="出版社")
      price = forms.DecimalField(label="价格",max_digits=8, decimal_places=2)
      gender=forms.ChoiceField(choices=((1,"男"),(2,"女")))

(4) Choices的问题:小元组的内容是固定的,无法随着数据库的更改二更改,不灵活

3.ModelChoiceField属性

作用:帮助渲染前端页面的下拉框

优势:ModelChoiceField可以接收queryset属性的参数,内容可以随着数据库的更改而更改

例:

1 class BookForm(forms.Form):
2     title = forms.CharField(label="书名",max_length=32)
3     gender=forms.ChoiceField(choices=((1,"男"),(2,"女")))
4     publish=forms.ModelChoiceField(queryset=Publish.objects.all())

4.ModelMultipleChoiceField属性

作用:帮助前端渲染页面的多选框,内容也能随着数据库的改变而改变

例:

1 class BookForm(forms.Form): 2     gender=forms.ChoiceField(choices=((1,"男"),(2,"女"))) 3     publish=forms.ModelChoiceField(queryset=Publish.objects.all()) 4     author=forms.ModelMultipleChoiceField(queryset=Author.objects.all())

二. modelForm组件

1.作用:

  正常情况下的model和form是没有关系的,所有forms组件必须我们自己编写,但是ModelForm可以与model之间形成对应关系,这样就免去了我们自己写model

2.语法:

(1)需要先引入forms组件的model类:from django.forms import ModelForm

(2)编写ModelForm类:

1 class BookModelForm(forms.ModelForm):
2     class Meta:
3         model=Book  #与之关联的模型类
4         # fields="__all__"  #可以渲染所有字段
5         fields=["title","price"]  #可以渲染部分字段
6 
7         exclide=[“title”]  #可以渲染除某些字段外的所有字段

(3)为公共字段或大多数字段添加内容,批量处理(添加__init__方法)

Input标签的样式属性:

1 def __init__(self,*args,**kwargs):
2     super().__init__(*args,**kwargs)
3     for field in self.fields.values():
4         field.widget.attrs.update({"class":"form-control"})

将错误转换成中文:

1 def __init__(self,*args,**kwargs):
2     super().__init__(*args,**kwargs)
3     for field in self.fields.values():
4         field.error_messages={"required":"不能为空"}

(4)为单个字段添加内容(当每个字段的内容不同时)

 1 Labels方法:
 2 
 3 class BookModelForm(forms.ModelForm):
 4         class Meta:
 5             model=Book
 6             fields="__all__"
 7             labels={"title":"书籍名称","price":"价格"}
 8 
 9 error_messages方法:
10 
11 class BookModelForm(forms.ModelForm):
12     class Meta:
13         model=Book
14         fields="__all__"
15         error_messages={"title":{"required":"书籍名称不能为空"}}
16 
17 widgets字段:
18 
19 先引入:from django.forms import widgets as Fwidgets
20 
21 class BookModelForm(forms.ModelForm):
22     class Meta:
23         model=Book
24         fields="__all__"
25         widgets = {
26             'pub_date': Fwidgets.Input(attrs={'type': 'date'})
27         }

3.forms组件有的接口,modelform也有,如is_valid,clean_data,errors

除了forms组件有的接口外,modelform还有save方法

Save方法会自动将干净的数据添加到表中,含有一对一,一对多,多对多的字段和表也会被处理好

4.编辑页面,默认value值得做法:

(1)取到待编辑的model对象

例:book_obj=Book.objects.fillter(id=1).first()

(2)将model对象传入modelform

例:form=BookModelForm(request.POST,instance=book_obj)

得到的form就是待前端页面渲染的对象

结果:如果对ModelForm传了instance就相当于更新操作,没传instance,就相当于创建操作

三.include

作用:当某一段代码被重复利用的次数很多时,可以将其写到一个文件中,其他地方引用即可,减少代码的冗余性

例:在form.html中

 1 <form action="" method="post" novalidate>
 2     {% csrf_token %}
 3       {% for field in form %}
 4             <div class="form-group">
 5                  <label for="title">{{ field.label }}</label>
 6                  {{ field }}
 7                  <span>{{ field.errors.0 }}</span>
 8             </div>
 9      {% endfor %}
10     <input type="submit" value="提交" class="btn btn-default pull-right">
11 </form>

在增加书籍页面中:

 1 <!DOCTYPE html>
 2 <html lang="zh-CN">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>Title</title>
 6     <meta name="viewport" content="width=device-width, initial-scale=1">
 7      <!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
 8     <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css"
 9           integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
10 
11 </head>
12 <body>
13 <h3>添加书籍</h3>
14 <div class="container">
15     <div class="row">
16         <div class="col-md-6 col-md-offset-3">
17            {% include 'form.html' %}  #代表将form.html中的代码放到这里
18         </div>
19     </div>
20 </div>
21 </body>
22 </html>

四.ModelForm的使用模板(做添加和编辑页面)

1.在models.py中:正常写模型表

 1   class Book(models.Model):
 2      nid=models.AutoField(primary_key=True)
 3      title=models.CharField(max_length=32)
 4      price=models.DecimalField(max_digits=8,decimal_places=2) # 999999.99
 5      pub_date=models.DateTimeField()  # "2012-12-12"
 6      publish=models.ForeignKey(to="Publish",on_delete=models.CASCADE) 
 7      authors=models.ManyToManyField(to="Author")
 8 
 9 
10    def __str__(self):
11        return self.title

2.在form.py中:构建ModelForm

 1 from django.forms import widgets as Fwidgets
 2 class BookModelForm(forms.ModelForm):
 3     class Meta:
 4         model=Book
 5         fields="__all__"
 6         labels={"title":"书籍名称","price":"价格"}
 7         widgets = {
 8             'pub_date': Fwidgets.Input(attrs={'type': 'date'})
 9         }
10     def __init__(self,*args,**kwargs):
11         super().__init__(*args,**kwargs)
12         for field in self.fields.values():
13             field.widget.attrs.update({"class":"form-control"})
14             field.error_messages={"required":"不能为空"}
15 
16 等同于写了以下代码:
17 
18 class BookForm(forms.Form):
19 
20 
21 title=forms.CharField(max_length=32)
22 price=forms.IntegerField()
23 pub_date=forms.DateField(widget=widgets.TextInput(attrs={"type":"date"}))
24 #publish=forms.ChoiceField(choices=[(1,"AAA"),(2,"BBB")])
25 publish=forms.ModelChoiceField(queryset=Publish.objects.all())
26 authors=forms.ModelMultipleChoiceField(queryset=Author.objects.all())

3.添加逻辑

 1 def add(request):
 2 
 3 if GET请求:
 4 
 5 form=BookModelForm()
 6 
 7 return render(request,{“form”:form})
 8 
 9 else POST请求:
10 
11 form=BookModelForm(request.POST)
12 
13 if form.is_valid():
14 
15 form.save()
16 
17 return render(“/”)
18 
19 else:
20 
21 return render(request,{“form”:form})

4.编辑逻辑

 1 def edit(request,id):
 2 
 3 edit_obj=Book.objects.get(pk=id)
 4 
 5 if GET请求:
 6 
 7 form=BookModelForm(instance=edit_obj)
 8 
 9 return render(request,{“form”:form})
10 
11 else POST请求:
12 
13 form=BookModelForm(request.POST,instance=edit_obj)
14 
15 if form.is_valid():
16 
17 form.save()
18 
19 return rediecr(“/”)
20 
21 else:
22 
23 return render(request,{“form”:form})

5.登录和编辑共同的渲染页面

 1 <form action="" method="post" novalidate>
 2 
 3 
 4 {% csrf_token %}
 5   {% for field in form %}
 6       <div class="form-group">
 7           <label for="title">{{ field.label }}</label>
 8           {{ field }}
 9           <span>{{ field.errors.0 }}</span>
10       </div>
11  {% endfor %}
12 <input type="submit" value="提交" class="btn btn-default pull-right">
13 
14 
15 </form>

引用:★行者尚★