Django的Form表单
Django的Form表單
Django?Form?Form介紹
Form 表單是在前端向后端提交數據最常用的方式,同時在好多場景下都需要對用戶的輸入進行校驗。
以注冊為例,Form 需要的三件事:
要有一個注冊的頁面,頁面里面要有form表單
生成HTML代碼
form表單要能提交數據到后端,后端要做有效性校驗
數據有效性校驗
要把校驗的提示信息展示在頁面上
校驗信息返回并展示,保存原來填寫的內容
普通方式的注冊功能
視圖函數
# 注冊 def register(request):error_msg = ""if request.method == "POST":username = request.POST.get("name")pwd = request.POST.get("pwd")# 對注冊信息做校驗if len(username) < 6:# 用戶長度小于6位error_msg = "用戶名長度不能小于6位"else:# 將用戶名和密碼存到數據庫return HttpResponse("注冊成功")return render(request, "register.html", {"error_msg": error_msg})模板
<html lang="en"> <head><meta charset="UTF-8"><title>注冊頁面</title> </head> <body> <form action="/reg/" method="post">{% csrf_token %}<p>用戶名:<input type="text" name="name"></p><p>密碼:<input type="password" name="pwd"></p><p><input type="submit" value="注冊"><p style="color: red">{{ error_msg }}</p></p> </form> </body> </html>Django 的 Form 組件
所以,Django 的 Form 組件對應上面所提三件事:
生成頁面可用的HTML標簽
對用戶提交的數據進行校驗
保留上次輸入內容
創建 Form 類
創建 Form 類時,主要涉及到 【字段】 和 【插件】,字段用于對用戶請求數據的驗證,插件用于自動生成 HTML;
要導入的包:
-
from django import forms
這是 Form 組件的父類,用于創建 Form 類 -
from django.forms import widgets
用于對每個字段指定樣式
字段與插件
initial 初始值
初始值,input 框里面的初始值
class RegForm(forms.Form):username = forms.CharField(min_length=8,label="用戶名",initial="張三"# 設置默認值)pwd = forms.CharField(min_length=6, label="密碼")error_messages
重寫錯誤信息。
class RegForm(forms.Form):name = forms.CharField(# 校驗規則相關max_length=16,label="用戶名",error_messages={"required": "該字段不能為空","invalid": "格式錯誤","man_length": "用戶名最長16位"},# widget控制的是生成HTML代碼相關的規則widget=widgets.TextInput(attrs={"class": "form-control"}))password
- render_value=True 提交后輸入框內容依然存在
radioSelect
單radio值為字符串
class RegForm(forms.Form):……gender = forms.fields.ChoiceField(choices=((1, "男"), (2, "女"), (3, "保密")),label="性別",initial=3,widget=forms.widgets.RadioSelect())單選 Select
class RegForm(forms.Form):...hobby = forms.fields.ChoiceField(choices=((1, "籃球"), (2, "足球"), (3, "雙色球"), ),label="愛好",initial=3,widget=forms.widgets.Select())多選 Select
class RegForm(forms.Form):...hobby = forms.fields.MultipleChoiceField(choices=((1, "籃球"), (2, "足球"), (3, "雙色球"), ),label="愛好",initial=[1, 3],widget=forms.widgets.SelectMultiple())單選 checkbox
class RegForm(forms.Form):...keep = forms.fields.ChoiceField(label="是否記住密碼",initial="checked",widget=forms.widgets.CheckboxInput())多選 checkbox
class RegForm(forms.Form):...hobby = forms.fields.MultipleChoiceField(choices=((1, "籃球"), (2, "足球"), (3, "雙色球"),),label="愛好",initial=[1, 3],widget=forms.widgets.CheckboxSelectMultiple())Django Form 所有內置字段
Fieldrequired=True, 是否允許為空widget=None, HTML插件label=None, 用于生成Label標簽或顯示內容initial=None, 初始值help_text='', 幫助信息(在標簽旁邊顯示)error_messages=None, 錯誤信息 {'required': '不能為空', 'invalid': '格式錯誤'}validators=[], 自定義驗證規則localize=False, 是否支持本地化disabled=False, 是否可以編輯label_suffix=None Label內容后綴CharField(Field)max_length=None, 最大長度min_length=None, 最小長度strip=True 是否移除用戶輸入空白IntegerField(Field)max_value=None, 最大值min_value=None, 最小值FloatField(IntegerField)...DecimalField(IntegerField)max_value=None, 最大值min_value=None, 最小值max_digits=None, 總長度decimal_places=None, 小數位長度BaseTemporalField(Field)input_formats=None 時間格式化 DateField(BaseTemporalField) 格式:2015-09-01 TimeField(BaseTemporalField) 格式:11:12 DateTimeField(BaseTemporalField)格式:2015-09-01 11:12DurationField(Field) 時間間隔:%d %H:%M:%S.%f...RegexField(CharField)regex, 自定制正則表達式max_length=None, 最大長度min_length=None, 最小長度error_message=None, 忽略,錯誤信息使用 error_messages={'invalid': '...'}EmailField(CharField) ...FileField(Field)allow_empty_file=False 是否允許空文件ImageField(FileField) ...注:需要PIL模塊,pip3 install Pillow以上兩個字典使用時,需要注意兩點:- form表單中 enctype="multipart/form-data"- view函數中 obj = MyForm(request.POST, request.FILES)URLField(Field)...BooleanField(Field) ...NullBooleanField(BooleanField)...ChoiceField(Field)...choices=(), 選項,如:choices = ((0,'上海'),(1,'北京'),)required=True, 是否必填widget=None, 插件,默認select插件label=None, Label內容initial=None, 初始值help_text='', 幫助提示ModelChoiceField(ChoiceField)... django.forms.models.ModelChoiceFieldqueryset, # 查詢數據庫中的數據empty_label="---------", # 默認空顯示內容to_field_name=None, # HTML中value的值對應的字段limit_choices_to=None # ModelForm中對queryset二次篩選ModelMultipleChoiceField(ModelChoiceField)... django.forms.models.ModelMultipleChoiceFieldTypedChoiceField(ChoiceField)coerce = lambda val: val 對選中的值進行一次轉換empty_value= '' 空值的默認值MultipleChoiceField(ChoiceField)...TypedMultipleChoiceField(MultipleChoiceField)coerce = lambda val: val 對選中的每一個值進行一次轉換empty_value= '' 空值的默認值ComboField(Field)fields=() 使用多個驗證,如下:即驗證最大長度20,又驗證郵箱格式fields.ComboField(fields=[fields.CharField(max_length=20), fields.EmailField(),])MultiValueField(Field)PS: 抽象類,子類中可以實現聚合多個字典去匹配一個值,要配合MultiWidget使用SplitDateTimeField(MultiValueField)input_date_formats=None, 格式列表:['%Y--%m--%d', '%m%d/%Y', '%m/%d/%y']input_time_formats=None 格式列表:['%H:%M:%S', '%H:%M:%S.%f', '%H:%M']FilePathField(ChoiceField) 文件選項,目錄下文件顯示在頁面中path, 文件夾路徑match=None, 正則匹配recursive=False, 遞歸下面的文件夾allow_files=True, 允許文件allow_folders=False, 允許文件夾required=True,widget=None,label=None,initial=None,help_text=''GenericIPAddressFieldprotocol='both', both,ipv4,ipv6支持的IP格式unpack_ipv4=False 解析ipv4地址,如果是::ffff:192.0.2.1時候,可解析為192.0.2.1, PS:protocol必須為both才能啟用SlugField(CharField) 數字,字母,下劃線,減號(連字符)...UUIDField(CharField) uuid類型Django Form內置字段生成 HTML 頁面
方式一:自動填寫
在模板文件 form 中,加入 {{ form_obj.as_p }} 就可以自動生成了。
優點:方便
缺點:不能添加 CSS 樣式
?
?
方式二:逐個手寫
優點:能夠為各個標簽添加 CSS 樣式類,也可以使用 Bootstrap 樣式類等
缺點:代碼量較大
?
form2
?
校驗
做校驗
通過函數 is_valid 做校驗,校驗后的各種字段數據會保存在 form_obj.clean_data 中。
if request.method == "POST":# 更新form_obj的內容form_obj = RegForm(request.POST)# form自己可以做校驗if form_obj.is_valid():# 1. form_obj.cleaned_data存儲form校驗后的內容,需要在is-valid函數后使用del form_obj.cleaned_data["re_pwd"]在模板頁面,使用 Form實例.字段名.errors.0的方式來顯示后端發來的校驗信息。
<div class="form-group {% if form_obj.name.errors.0 %} has-error {% endif %}">{{ form_obj.name.label }}{{ form_obj.name }}<span class="help-block">{{ form_obj.name.errors.0 }}</span> </div>Form 類自帶校驗字段
Form 類設置的各種字段的值自動包含所要校驗的內容,而校驗結果顯示的信息放在 error_messages 字段中。
re_pwd = forms.CharField(label="確認密碼",min_length=6,max_length=10,widget=widgets.PasswordInput(attrs={"class": "form-control"}, render_value=True),error_messages={"min_length": "密碼不能少于6位!","max_length": "密碼最長10位!","required": "該字段不能為空!"})Form 自帶的正則校驗
除了 Form 類中的字段能夠校驗外,還需要根據需求自定義校驗,其中,正則校驗就是一個比較常用的校驗方式, Form 類中自帶正則校驗方法。
from django import forms from django.forms import widgets from django.core.validators import RegexValidator from django.core.exceptions import ValidationErrormobile = forms.CharField(label="手機",# 自己定制校驗規則validators=[RegexValidator(r'^[0-9]+$',"手機號必須是數字"),RegexValidator(r'^1[3-9][0-9]{9}$', "手機格式不正確")],widget=widgets.TextInput(attrs={"class": "form-control"}),error_messages={"required": "該字段不能為空"})具體字段的自定義校驗方法
在 Form 類中加上 clean_XX 函數,可在其中自定義對 XX 字段的校驗。這種方法只能使用此字段。
在此函數中,
- 如果校驗出錯,通過 raise ValidationError("錯誤提示信息") 方式拋出提示信息
- 函數的最后,即校驗成功,返回該字段, return XX
全局的自定義校驗方法
在 Form 類中,重寫 clean 函數,可以實現對多個字段的自定義校驗。
添加提示信息的方法:
self.add_error("要添加到哪個字段的錯誤信息", ValidationError("提示的錯誤信息"))驗完成的最后都要將校驗字典返回:return self.cleaned_data
在模板頁面中,依然可以直接用所添加到字段的錯誤信息變量:form_obj.name.errors.0
示例:
def clean(self):pwd = self.cleaned_data.get("pwd")re_pwd = self.cleaned_data.get("re_pwd")if pwd != re_pwd:self.add_error("re_pwd", ValidationError("兩次密碼不一致!"))# raise ValidationError("兩次密碼不一致")return self.cleaned_dataForm 與數據庫
有時候會遇到這樣的需求:前端頁面中,Form 表單里的數據是從數據庫中取出來顯示出來,此時如果向數據庫中添加新的數據,前端頁面不會顯示出新添加的數據,只有在重啟后端服務后才能重新從數據庫中取出數據,便包含了新添加的數據。
解決方法:
在對 Form 類中要從數據庫中取數據的字段來說,在該字段進行取數據,所以需要在每次實例化類的時候都重新對該字段進行賦值。
city = forms.ChoiceField( choices=models.City.objects.all().values_list("id", "name"),label="所在城市",initial=1,widget=widgets.Select(attrs={"class": "form-control"}) )# 重寫父類的初始化方法, 每次實例化類的時候都調用 def __init__(self, *args, **kwargs):super().__init__(*args, **kwargs)# 每次實例化類的時候都重新給choices賦值,保證更新數據庫時數據同步更新self.fields["city"].widget.choices = models.City.objects.all().values_list("id", "name")參考:https://www.cnblogs.com/liwenzhou/p/8747872.html
GitHub地址:https://github.com/protea-ban/oldboy/tree/master/s9day73/ajaxdemo
?
轉載于:https://www.cnblogs.com/banshaohuan/p/9531807.html
總結
以上是生活随笔為你收集整理的Django的Form表单的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何正确的阅读Datasheet?
- 下一篇: 可持久化平衡树