一. Forms組件補充
1.__init__()
如果繼承forms.Form的類中的每一個字段,或者大部分字段都做了相同的約束,可以將該約束放到__init__中編寫
實例:每一個字段都需要添加form-control類名
1 class BookForm(forms.Form): 2 title = forms.CharField(max_length=32) 3 pub_date = forms.DateField() 4 price = forms.DecimalField(max_digits=8, decimal_places=2) 5 6 def __init__(self,*args,**kwargs): 7 super().__init__(*args,**kwargs) 8 for field in self.fields.values(): 9 field.widget.attrs.update({"class":"form-control"})
2.ChoiceField屬性,下拉菜單(元組套元組的形式)
(1)choices作用:在數據庫中用元組的第一項作為存儲的值,在顯示時,將元組的第二項作為顯示的內容,便於前端使用下拉框
例:
1 class Book(models.Model): 2 id=models.AutoField(primary_key=True) 3 title=models.CharField(max_length=32) 4 gender=models.IntegerField(choices=((1,"男"),(2,"女")),default=1)
(2)與get_gender_display()方法同時使用,用來獲取元組第二項的內容
(3)在forms組件中渲染時,只需將類型改變成ChoiceField()
例:
1 class BookForm(forms.Form): 2 title = forms.CharField(label="書名",max_length=32) 3 pub_date = forms.DateField(label="出版社") 4 price = forms.DecimalField(label="價格",max_digits=8, decimal_places=2) 5 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>
