Django框架基础之Form组件
服务端假设所有用户提交的数据都是不可信任的,所以Django框架内置了form组件来验证用户提交的信息
form组件的2大功能:
1 验证(显示错误信息)
2 保留用户上次输入的信息
– 可以生成html标签
应用:
'''
遇到问题没人解答?小编创建了一个Python学习交流QQ群:857662006
寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
'''
class A_Form(Form):
字段=fields.字段类型(默认参数:
required=True,
widget=widgets.插件(attrs={}))
常用字段:Charfield,RegexField,IntegerField,EmailField
常用参数:max_length,min_length,
widget=widgets.Select(choices=models.Classes.objects.values_list('id','title'))
error_messages={
'required':'用户名不能为空',
'max_length':'太长了',
'min_length':'太短了',
}
label='用户名', # obj.t1.label
disabled=False, # 是否可以编辑
label_suffix='--->', # Label内容后缀
help_text='。。。。。。', # 提供帮助信息
obj=A_Form(initial='')#生成空的html标签,含有默认值
obj=A-Form(request.POST)#拿到浏览器请求,传入form做验证
obj.is_valid()#判断验证是否通过
obj.cleaned_data()#验证通过后的值 字典形式
obj.errors #form 返回的错误信息 是个对象 'obj.errors.字典.0 ' 获取第一个错误信息
原理:
LoginForm实例化时:self.fields={
'username':正则表达式
'password':正则表达式}
循环self.fields
flag=True
errors
cleaned_data
for k,v in self.fields.items():
username ,正则
input_value=request.POST.get(k)
input_value,正则
flag=false /true
return flag
'''
遇到问题没人解答?小编创建了一个Python学习交流QQ群:857662006
寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
'''
ModelForm
a. class Meta:
model, # 对应Model的
fields=None, # 字段
exclude=None, # 排除字段
labels=None, # 提示信息
help_texts=None, # 帮助提示信息
widgets=None, # 自定义插件
error_messages=None, # 自定义错误信息(整体错误信息from django.core.exceptions import NON_FIELD_ERRORS)
field_classes=None # 自定义字段类 (也可以自定义字段)
localized_fields=('birth_date',) # 本地化,如:根据不同时区显示数据
如:
数据库中
2016-12-27 04:10:57
setting中的配置
TIME_ZONE = 'Asia/Shanghai'
USE_TZ = True
则显示:
2016-12-27 12:10:57
b. 验证执行过程
is_valid -> full_clean -> 钩子 -> 整体错误
c. 字典字段验证
def clean_字段名(self):
# 可以抛出异常
# from django.core.exceptions import ValidationError
return "新值"
d. 用于验证
model_form_obj = XXOOModelForm()
model_form_obj.is_valid()
model_form_obj.errors.as_json()
model_form_obj.clean()
model_form_obj.cleaned_data
e. 用于创建
model_form_obj = XXOOModelForm(request.POST)
#### 页面显示,并提交 #####
# 默认保存多对多
obj = form.save(commit=True)
# 不做任何操作,内部定义 save_m2m(用于保存多对多)
obj = form.save(commit=False)
obj.save() # 保存单表信息
obj.save_m2m() # 保存关联多对多信息
f. 用于更新和初始化
obj = model.tb.objects.get(id=1)
model_form_obj = XXOOModelForm(request.POST,instance=obj)
...
PS: 单纯初始化
model_form_obj = XXOOModelForm(initial={...})
扩展:
1.由于form组件中每个字段都是类的数据属性(全局变量),在类每次实例化之后,数据属性不会发生改变,会保留上次的更新结果
导致无法动态显示数据库的内容
'''
遇到问题没人解答?小编创建了一个Python学习交流QQ群:857662006
寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
'''
解决方法一:每次实例化之前,更新xx字段的值
xx=fields.MultipleChoiceField(
# choices=models.Classes.objects.values_list('id','title'),
widget=widgets.SelectMultiple
)
def __init__(self,*args,**kwargs):
super(TeacherForm,self).__init__(*args,**kwargs)
self.fields['xx'].choices=models.Classes.objects.values_list('id','title')
解决方法二:不推荐
from django.forms import models as form_model
xx=form_model.ModelMultipleChoiceField(queryset=models.Classes.objects.all())
models中:
def __str__(self):
return self.title
\2. 扩展字段
'''
遇到问题没人解答?小编创建了一个Python学习交流QQ群:857662006
寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
'''
单选:ChoiceField
多选:MultipleChoiceField
Select框:
单选
cls_id = fields.IntegerField(
# widget=widgets.Select(choices=[(1,'上海'),(2,'北京')])
widget=widgets.Select(choices=models.Classes.objects.values_list('id','title'))
)
cls_id = fields.ChoiceField(
choices=models.Classes.objects.values_list('id','title'),
widget=widgets.Select(attrs={'class': 'form-control'})
)
obj = FooForm({'cls_id':1})
多选
xx = fields.MultipleChoiceField(
choices=models.Classes.objects.values_list('id','title'),
widget=widgets.SelectMultiple
)
obj = FooForm({'cls_id':[1,2,3]})
文件:FileField
常用选择插件
'''
遇到问题没人解答?小编创建了一个Python学习交流QQ群:857662006
寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
'''
1 # 单radio,值为字符串
2 # user = fields.CharField(
3 # initial=2,
4 # widget=widgets.RadioSelect(choices=((1,'上海'),(2,'北京'),))
5 # )
6
7 # 单radio,值为字符串
8 # user = fields.ChoiceField(
9 # choices=((1, '上海'), (2, '北京'),),
10 # initial=2,
11 # widget=widgets.RadioSelect
12 # )
13
14 # 单select,值为字符串
15 # user = fields.CharField(
16 # initial=2,
17 # widget=widgets.Select(choices=((1,'上海'),(2,'北京'),))
18 # )
19
20 # 单select,值为字符串
21 # user = fields.ChoiceField(
22 # choices=((1, '上海'), (2, '北京'),),
23 # initial=2,
24 # widget=widgets.Select
25 # )
26
27 # 多选select,值为列表
28 # user = fields.MultipleChoiceField(
29 # choices=((1,'上海'),(2,'北京'),),
30 # initial=[1,],
31 # widget=widgets.SelectMultiple
32 # )
33
34
35 # 单checkbox
36 # user = fields.CharField(
37 # widget=widgets.CheckboxInput()
38 # )
39
40
41 # 多选checkbox,值为列表
42 # user = fields.MultipleChoiceField(
43 # initial=[2, ],
44 # choices=((1, '上海'), (2, '北京'),),
45 # widget=widgets.CheckboxSelectMultiple
46 # )
扩展插件
'''
遇到问题没人解答?小编创建了一个Python学习交流QQ群:857662006
寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
'''
1 扩展插件:
2 Textarea
3 CheckboxInput
4 CheckboxSelectMultiple
5 RadioSelect
6 FileInput
7
8 t1=fields.CharField(
9 widget=widgets.Textarea(attrs={})
10 )
11 t2=fields.CharField(
12 widget=widgets.CheckboxInput
13 )
14 t3=fields.MultipleChoiceField(
15 choices=[(1,'篮球'),(2,'足球')],
16 widget=widgets.CheckboxSelectMultiple
17 )
18 t4=fields.ChoiceField(
19 choices=[(1,'篮球'),(2,'足球')],
20 widget=widgets.RadioSelect
21 )
22 t5=fields.FileField(
23 widget=widgets.FileInput
24 )
Django内置字段:
'''
遇到问题没人解答?小编创建了一个Python学习交流QQ群:857662006
寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
'''
1 Field
2 required=True, 是否允许为空
3 widget=None, HTML插件
4 label=None, 用于生成Label标签或显示内容
5 initial=None, 初始值
6 help_text='', 帮助信息(在标签旁边显示)
7 error_messages=None, 错误信息 {'required': '不能为空', 'invalid': '格式错误'}
8 show_hidden_initial=False, 是否在当前插件后面再加一个隐藏的且具有默认值的插件(可用于检验两次输入是否一直)
9 validators=[], 自定义验证规则
10 localize=False, 是否支持本地化
11 disabled=False, 是否可以编辑
12 label_suffix=None Label内容后缀
13
14
15 CharField(Field)
16 max_length=None, 最大长度
17 min_length=None, 最小长度
18 strip=True 是否移除用户输入空白
19
20 IntegerField(Field)
21 max_value=None, 最大值
22 min_value=None, 最小值
23
24 FloatField(IntegerField)
25 ...
26
27 DecimalField(IntegerField)
28 max_value=None, 最大值
29 min_value=None, 最小值
30 max_digits=None, 总长度
31 decimal_places=None, 小数位长度
32
33 BaseTemporalField(Field)
34 input_formats=None 时间格式化
35
36 DateField(BaseTemporalField) 格式:2015-09-01
37 TimeField(BaseTemporalField) 格式:11:12
38 DateTimeField(BaseTemporalField)格式:2015-09-01 11:12
39
40 DurationField(Field) 时间间隔:%d %H:%M:%S.%f
41 ...
42
43 RegexField(CharField)
44 regex, 自定制正则表达式
45 max_length=None, 最大长度
46 min_length=None, 最小长度
47 error_message=None, 忽略,错误信息使用 error_messages={'invalid': '...'}
48
49 EmailField(CharField)
50 ...
51
52 FileField(Field)
53 allow_empty_file=False 是否允许空文件
54
55 ImageField(FileField)
56 ...
57 注:需要PIL模块,pip3 install Pillow
58 以上两个字典使用时,需要注意两点:
59 - form表单中 enctype="multipart/form-data"
60 - view函数中 obj = MyForm(request.POST, request.FILES)
61
62 URLField(Field)
63 ...
64
65
66 BooleanField(Field)
67 ...
68
69 NullBooleanField(BooleanField)
70 ...
71
72 ChoiceField(Field)
73 ...
74 choices=(), 选项,如:choices = ((0,'上海'),(1,'北京'),)
75 required=True, 是否必填
76 widget=None, 插件,默认select插件
77 label=None, Label内容
78 initial=None, 初始值
79 help_text='', 帮助提示
80
81
82 ModelChoiceField(ChoiceField)
83 ... django.forms.models.ModelChoiceField
84 queryset, # 查询数据库中的数据
85 empty_label="---------", # 默认空显示内容
86 to_field_name=None, # HTML中value的值对应的字段
87 limit_choices_to=None # ModelForm中对queryset二次筛选
88
89 ModelMultipleChoiceField(ModelChoiceField)
90 ... django.forms.models.ModelMultipleChoiceField
91
92
93
94 TypedChoiceField(ChoiceField)
95 coerce = lambda val: val 对选中的值进行一次转换
96 empty_value= '' 空值的默认值
97
98 MultipleChoiceField(ChoiceField)
99 ...
100
101 TypedMultipleChoiceField(MultipleChoiceField)
102 coerce = lambda val: val 对选中的每一个值进行一次转换
103 empty_value= '' 空值的默认值
104
105 ComboField(Field)
106 fields=() 使用多个验证,如下:即验证最大长度20,又验证邮箱格式
107 fields.ComboField(fields=[fields.CharField(max_length=20), fields.EmailField(),])
108
109 MultiValueField(Field)
110 PS: 抽象类,子类中可以实现聚合多个字典去匹配一个值,要配合MultiWidget使用
111
112 SplitDateTimeField(MultiValueField)
113 input_date_formats=None, 格式列表:['%Y--%m--%d', '%m%d/%Y', '%m/%d/%y']
114 input_time_formats=None 格式列表:['%H:%M:%S', '%H:%M:%S.%f', '%H:%M']
115
116 FilePathField(ChoiceField) 文件选项,目录下文件显示在页面中
117 path, 文件夹路径
118 match=None, 正则匹配
119 recursive=False, 递归下面的文件夹
120 allow_files=True, 允许文件
121 allow_folders=False, 允许文件夹
122 required=True,
123 widget=None,
124 label=None,
125 initial=None,
126 help_text=''
127
128 GenericIPAddressField
129 protocol='both', both,ipv4,ipv6支持的IP格式
130 unpack_ipv4=False 解析ipv4地址,如果是::ffff:192.0.2.1时候,可解析为192.0.2.1, PS:protocol必须为both才能启用
131
132 SlugField(CharField) 数字,字母,下划线,减号(连字符)
133 ...
134
135 UUIDField(CharField) uuid类型
136 ...
Django内置插件:
TextInput(Input)
NumberInput(TextInput)
EmailInput(TextInput)
URLInput(TextInput)
PasswordInput(TextInput)
HiddenInput(TextInput)
Textarea(Widget)
DateInput(DateTimeBaseInput)
DateTimeInput(DateTimeBaseInput)
TimeInput(DateTimeBaseInput)
CheckboxInput
Select
NullBooleanSelect
SelectMultiple
RadioSelect
CheckboxSelectMultiple
FileInput
ClearableFileInput
MultipleHiddenInput
SplitDateTimeWidget
SplitHiddenDateTimeWidget
SelectDateWidget
3 额外的正则:
user = fields.CharField(
validators=[RegexValidator(r'^[0-9]+$', '请输入数字'), RegexValidator(r'^159[0-9]+$', '数字必须以159开头')])
4 页面展示:
1 obj = Foo()
2 obj = Foo(init..)
3
4 # 灵活
5 <form>
6 {{obj.xx}}
7 {{obj.xx}}
8 {{obj.xx}}
9 {{obj.xx}}
10 </form>
11 # 简单
12 {{obj.as_p}}
13 <ul>
14 {{obj.as_ul}}
15 </ul>
16 <table>
17 {{obj.as_table}}
18 </table>
5 定制:
class Test1Form(Form):
user = fields.CharField(validators=[])
pwd = fields.CharField()
# 为每个字段定制自己的要求 必须要有返回值
def clean_user(self):
v = self.cleaned_data['user']
if models.Student.objects.filter(name=v).count():
raise ValidationError('用户名已经存在')
return self.cleaned_data['user']
def clean_pwd(self):
return self.cleaned_data['pwd']
# 为所有字段定制统一的要求
def clean(self):
# user = self.cleaned_data.get('user')
# email = self.cleaned_data.get('email')
# if models.Student.objects.filter(user=user,email=email).count():
# raise ValidationError('用户名和邮箱联合已经存在')
return self.cleaned_data
本文来自博客园,作者:I'm_江河湖海,转载请注明原文链接:https://www.cnblogs.com/jhhh/p/16764000.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架