Django form組件

form組件博客整理
一.背景
咱們以前在HTML頁面中利用form表單向後端提交數據時,都會寫一些獲取用戶輸入的標籤而且用form標籤把它們包起來。
與此同時咱們在好多場景下都須要對用戶的輸入作校驗,好比校驗用戶是否輸入,輸入的長度和格式等正不正確。若是用戶輸入的
內容有錯誤就須要在頁面上相應的位置顯示對應的錯誤信息。Django form組件就實現了上面所述的功能
form組件主要功能以下:
生成頁面可用的HTML標籤
對用戶提交的數據進行校驗
保留上次輸入的內容
二. 註冊功能(普通方式)
views.py:
def register(request):
error_msg=''
if request.method=='POST':
username = request.POST.get("name")
pwd = request.POST.get("pwd")
# 對註冊信息作校驗
if len(username) < 6:
error_msg = "用戶名長度不能小於6位"
else:
#將用戶名和密碼存到數據庫
return Httpresponse(' 註冊成功')
return render(request,'register.html',{'error_msg':error_msg})
login.html
<!DOCTYPE html>
<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>
二.註冊功能(form組件)
views.py
寫類:
from django import forms
class RegForm(forms.Form):
name = forms.CharField(label="用戶名")
pwd = forms.CharField(label="密碼")
視圖函數:
def register2(request):
form_obj = RegForm()
if request.method == "POST":
# 實例化form對象的時候,把post提交過來的數據直接傳進去
form_obj = RegForm(request.POST)
# 調用form_obj校驗數據的方法
if form_obj.is_valid():
return HttpResponse("註冊成功")
return render(request, "register2.html", {"form_obj": form_obj})
login.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>註冊2</title>
</head>
<body>
<form action="/reg2/" method="post" novalidate autocomplete="off">
{% csrf_token %}
<div>
<label for="{{ form_obj.name.id_for_label }}">{{ form_obj.name.label }}</label>
{{ form_obj.name }} {{ form_obj.name.errors.0 }}
</div>
<div>
<label for="{{ form_obj.pwd.id_for_label }}">{{ form_obj.pwd.label }}</label>
{{ form_obj.pwd }} {{ form_obj.pwd.errors.0 }}
</div>
<div>
<input type="submit" class="btn btn-success" value="註冊">
</div>
</form>
</body>
</html>
看網頁效果發現 也驗證了form的功能:
• 前端頁面是form類的對象生成的 -->生成HTML標籤功能
• 當用戶名和密碼輸入爲空或輸錯以後 頁面都會提示 -->用戶提交校驗功能
• 當用戶輸錯以後 再次輸入 上次的內容還保留在input框 -->保留上次輸入內容
三.Form 經常使用字段與插件
字段用於對用戶請求數據的驗證
插件用於自動生成HTML;
1.initial 初始值,input框裏面的初始值。
class LoginForm(forms.Form):
username = forms.CharField(
min_length=8,
label="用戶名",
initial="張三" # 設置默認值
)
pwd = forms.CharField(min_length=6, label="密碼")
2.error_messages 重寫錯誤信息。
class LoginForm(forms.Form):
username = forms.CharField(
min_length=8,
label="用戶名",
initial="張三",
error_messages={
"required": "不能爲空",
"invalid": "格式錯誤",
"min_length": "用戶名最短8位"
}
)
pwd = forms.CharField(min_length=6, label="密碼")
3.password
class LoginForm(forms.Form):
...
pwd = forms.CharField(
min_length=6,
label="密碼",
widget=forms.widgets.PasswordInput(attrs={'class': 'c1'}, render_value=True)
)
4.radioSelect 單radio值爲字符串
class LoginForm(forms.Form):
username = forms.CharField(
min_length=8,
label="用戶名",
initial="張三",
error_messages={
"required": "不能爲空",
"invalid": "格式錯誤",
"min_length": "用戶名最短8位"
}
)
pwd = forms.CharField(min_length=6, label="密碼")
gender = forms.fields.ChoiceField( #
choices=((1, "男"), (2, "女"), (3, "保密")),
label="性別",
initial=3,
widget=forms.widgets.RadioSelect()
)
5.單選Select
class LoginForm(forms.Form):
...
hobby = forms.fields.ChoiceField(
choices=((1, "籃球"), (2, "足球"), (3, "雙色球"), ),
label="愛好",
initial=3,
widget=forms.widgets.Select()
)
6.多選Select
class LoginForm(forms.Form):
...
hobby = forms.fields.MultipleChoiceField(
choices=((1, "籃球"), (2, "足球"), (3, "雙色球"), ),
label="愛好",
initial=[1, 3],
widget=forms.widgets.SelectMultiple()
)
7.單選checkbox
class LoginForm(forms.Form):
...
keep = forms.fields.ChoiceField(
label="是否記住密碼",
initial="checked",
widget=forms.widgets.CheckboxInput()
)
8.多選checkbox
class LoginForm(forms.Form):
...
hobby = forms.fields.MultipleChoiceField(
choices=((1, "籃球"), (2, "足球"), (3, "雙色球"),),
label="愛好",
initial=[1, 3],
widget=forms.widgets.CheckboxSelectMultiple()
)
關於choice的注意事項:
在使用選擇標籤時,須要注意choices的選項能夠從數據庫中獲取,可是因爲是靜態字段 ***獲取的值沒法實時更新***,那麼須要自
定義構造方法從而達到此目的。
方式一:
class MyForm(Form):

user = fields.ChoiceField(
# choices=((1, '上海'), (2, '北京'),),
initial=2,
widget=widgets.Select
)

def __init__(self, *args, **kwargs):
super(MyForm,self).__init__(*args, **kwargs)
# self.fields['user'].choices = ((1, '上海'), (2, '北京'),)
# 或
self.fields['user'].choices = models.Classes.objects.all().values_list('id','caption')
四.Django Form全部內置字段
Field
required=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:12

DurationField(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.ModelChoiceField
queryset, # 查詢數據庫中的數據
empty_label="---------", # 默認空顯示內容
to_field_name=None, # HTML中value的值對應的字段
limit_choices_to=None # ModelForm中對queryset二次篩選

ModelMultipleChoiceField(ModelChoiceField)
... django.forms.models.ModelMultipleChoiceField



TypedChoiceField(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=''

GenericIPAddressField
protocol='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類型
五.校驗
方式一:
from django.forms import Form
from django.forms import widgets
from django.forms import fields
from django.core.validators import RegexValidator

class MyForm(Form):
user = fields.CharField(
validators=[RegexValidator(r'^[0-9]+$', '請輸入數字'), RegexValidator(r'^159[0-9]+$', '數字必須以159開頭')],
)
方式二:
import re
from django.forms import Form
from django.forms import widgets
from django.forms import fields
from django.core.exceptions import ValidationError


# 自定義驗證規則
def mobile_validate(value):
mobile_re = re.compile(r'^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$')
if not mobile_re.match(value):
raise ValidationError('手機號碼格式錯誤')


class PublishForm(Form):


title = fields.CharField(max_length=20,
min_length=5,
error_messages={'required': '標題不能爲空',
'min_length': '標題最少爲5個字符',
'max_length': '標題最多爲20個字符'},
widget=widgets.TextInput(attrs={'class': "form-control",
'placeholder': '標題5-20個字符'}))


# 使用自定義驗證規則
phone = fields.CharField(validators=[mobile_validate, ],
error_messages={'required': '手機不能爲空'},
widget=widgets.TextInput(attrs={'class': "form-control",
'placeholder': u'手機號碼'}))

email = fields.EmailField(required=False,
error_messages={'required': u'郵箱不能爲空','invalid': u'郵箱格式錯誤'},
widget=widgets.TextInput(attrs={'class': "form-control", 'placeholder': u'郵箱'}))
六.ModelForm 本質幫助開發者對用戶請求中的數據進行格式校驗
form與model的終極結合。
class BookForm(forms.ModelForm):

class Meta:
model = models.Book
fields = "__all__"
labels = {
"title": "書名",
"price": "價格"
}
widgets = {
"password": forms.widgets.PasswordInput(attrs={"class": "c1"}),
}
class Meta:下經常使用參數:
model = models.Student # 對應的Model中的類
fields = "__all__" # 字段,若是是__all__,就是表示列出全部的字段
exclude = None # 排除的字段
labels = None # 提示信息
help_texts = None # 幫助提示信息
widgets = None # 自定義插件
error_messages = None # 自定義錯誤信息
示例:
  
class GoodsModelForm(forms.ModelForm):
class Meta:
model = models.Goods
fields = "__all__"
error_messages = {
'title':{'required':'商品名稱不能爲空'}
}

def __init__(self,*args,**kwargs): (重寫__init__給每個字段加上樣式)
super().__init__(*args,**kwargs)

for name,field in self.fields.items():
field.widget.attrs['class'] = 'form-control'
七.ModelFormSet 本質幫助開發者對用戶請求中的數據進行批量格式校驗。
  
class GoodsModelForm(forms.ModelForm):
class Meta:
model = models.Goods
fields = "__all__"
error_messages = {
'title':{'required':'商品名稱不能爲空'}
}

def __init__(self,*args,**kwargs): (重寫__init__給每個字段加上樣式)
super().__init__(*args,**kwargs)

for name,field in self.fields.items():
field.widget.attrs['class'] = 'form-control'
視圖中:
    
  from django.forms.models import modelformset_factory

  GoodsModelFormSet = modelformset_factory(model=models.Goods,form=GoodsModelForm,extra=1) 生成一個類
  if request.method == "GET":
  form_set = GoodsModelFormSet() get請求實例化對象
  return render(request,'multi_goods_add.html',{'form_set':form_set})
  form_set = GoodsModelFormSet(data=request.POST) post請求 實例化時將用戶傳遞過來的信息傳進去,
  if form_set.is_valid():
  form_set.save()
    else:
   print('校驗失敗')
  return render(request, 'multi_goods_add.html', {'form_set': form_set})
html中:
    必定要加
{{ form_set.management_form }}
八.將下拉框變成radio選擇框:
  

class GoodsModelForm(forms.ModelForm):
class Meta:
model = models.Goods
fields = "__all__"
error_messages = {
'title':{'required':'商品名稱不能爲空'}
}html

widgets = {
'source':forms.RadioSelect()
}前端

def __init__(self,*args,**kwargs):
super().__init__(*args,**kwargs)git

for name,field in self.fields.items():
if name == 'source':
# print(field,type(field))
# from django.forms.models import ModelChoiceField
field.empty_label = None
else:
field.widget.attrs['class'] = 'form-control'正則表達式

相關文章
相關標籤/搜索