forms组件
forms组件
功能:校验数据、渲染标签、展示信息
使用:导入forms模块,编写类继承forms.Form类
from django import forms
class MyForm(forms.Form):
pass
校验:
1.传入待校验的数据
form_obj = MyForm({...})
2.查看是否符合条件
form_obj.is_valid()
3.查看符合条件的数据
form_obj.cleaned_data
4.查看不符合条件的数据及原因
form_obj.errors
渲染标签
方式1:
{{ form_obj.as_p }}
{{ form_obj.as_table }}
{{ form_obj.as_ul }}
方式2:
{{ form_obj.username.label }}
{{ form_obj.username }}
{{ form_obj.password.label }}
{{ form_obj.password }}
方式3: # 推荐这种,按照forms的特性多的参数会被忽略
{% for obj in form_obj %}
{{ obj.label }}
{{ obj }}
{% endfor %}
展示信息
1.后端接收待检验的数据生成对象
form_obj = MyForm(...)
2.在前端页面上添加一行代码即可
{{ obj.errors.0 }}
3.自定义展示信息
字段参数
error_messages = {...}
label = ''
ps:form表单标签添加novalidate参数可以让浏览器不做校验
钩子🪝函数
钩子函数的含义就是在程序执行的过程中穿插额外的逻辑
比如校验用户名重复(校验单个字段)、校验密码和确认密码是否一致(校验多个字段)
'''钩子函数是数据经过了字段第一层参数校验之后才会执行'''
局部钩子
校验用户名重复
def clean_name(self): # 专门用于对name字段添加校验规则的函数名
name = self.cleaned_data.gat('name') # 获取用户名
is_exist = models.数据库.objects.filter(name=name) # 判断用户名是否存在
if is_exist:
self.add_error('name', '用户名已存在') # 抛出错误提示
return name # 不存在正常将name返回出去
全局钩子
校验密码和确认密码是否一致
def clean(self):
password = self.cleaned_data.get('password') # 获取密码
confirm_password = self.cleande_data.get('confirm_password') # 确认密码
if password != comfirm_password:
self.add_error('confirm_password', '密码不一致') # 抛出错误提示
forms组件字段参数
| 字段参数 | 作用 |
|---|---|
| min_length | 最小长度 |
| max_length | 最大长度 |
| label | 字段名称 |
| error_messages | 错误提示 |
| min_value | 最小值 |
| max_value | 最大值 |
| initial | 默认值 |
| validators | 正则校验器 |
正则校验器
from django.core.validators import RegexValidator
validators=[
RegexValidator(r'^[0-9]+$', '请输入数字'), # 因为经过了参数确认,不需要再额外控制位数
RegexValidator(r'^159[0-9]+$', '数字必须以159开头')] # 编写特定的正则
控制标签渲染
widget
🌰:
password = forms.CharField( widget=forms.widgets.PasswordInput(attrs={'class':'form-control'})
)
模板:
forms.widgets.控制type的类型(attrs=控制各项属性:class id ...)
选择标签内部对应关系
多选择编写对应关系
hobby = forms.MultipleChoiceField(
choices=((1, "于心有愧"), (2, "可一可再"), (3, "岁月如歌"),),
)
def __init__(self, *args, **kwargs):
super(MyForm,self).__init__(*args, **kwargs)
self.fields['hobby'].choices = models.Classes.objects.all().values_list('id','caption')
forms组件字段类型
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类型
forms组件源码分析
if form_obj.is_valid(): # 找到is_valid源代码,理解为什么我们编写的forms字段可以用is_valid判断
return HttpResponse("OK")
is_valid源码:
def is_valid(self):
"""
Returns True if the form has no errors. Otherwise, False. If errors are
being ignored, returns False.
翻译:如果表单没有错误则返回True。否则,假的。如果错误被忽略,则返回False。
"""
return self.is_bound and not self.errors #is_bound必须为True和errors必须为False
is_bound源码:
def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None,
initial=None, error_class=ErrorList, label_suffix=None,
empty_permitted=False, field_order=None, use_required_attribute=None, renderer=None):
self.is_bound = data is not None or files is not None
'''我们只用关注is_bound,发现他的True条件为data或者files不为空即可
data就是我们传入的数据类型,files是我们传入的文件类型,只要有值,就能满足True的条件'''
errors源码:
@property
def errors(self):
'''Returns an ErrorDict for the data provided for the form
翻译:为表单提供的数据返回一个ErrorDict'''
if self._errors is None: # 如果_errors为空
self.full_clean() #
return self._errors # 如果不为空,返回_errors
print(form_obj.is_valid, form_obj.is_valid())
<bound method BaseForm.is_valid of <MyForm bound=True, valid=False, fields=(name;phone;password;confirm_password;age;addr;email;file;files;gender;hobby;hobby1;keep;hobby2)>>
False
经过粗浅的源码分析:
个人理解为,is_valid会根据内容是否为空,和errors信息必须为False,这样就比较好理解了,我们编写的forms代码就会被进行判断,发现错误errors就会对其进行记录,只要errors为空,就证明了接受到的数据都满足了我们的forms要求。至于具体的检验,还需理解
ModelForm简介
我们在编写类的组件的时候,还需要到forms类中重新写一遍;使用ModelForm即可很好的结合forms与models的关系。
class MyUser(forms.ModelForm):
class Meta:
model = models.User # 指定关联的表
fields = '__all__' # 所有的字段全部生成对应的forms字段
labels = {
'name': '用户名',
'age': '年龄',
'addr': '地址',
'email': '邮箱'
}
widgets = {
"name": forms.widgets.TextInput(attrs={"class": "form-control"}),
}
def reg(request):
form_obj = MyUser()
if request.method == 'POST':
form_obj = MyUser(request.POST)
if form_obj.is_valid():
# form_obj.save() # 新增数据
edit_obj = models.User.objects.filter(pk=5).first()
form_obj = MyUser(request.POST, instance=edit_obj) # 是新增还是保存就取决于有没有instance参数
form_obj.save() # 编辑数据
return render(request, 'reg.html', locals())
cookie与session简介
HTTP协议的四大特性: 1.基于请求响应 2.基于TCP/UDP协议之上 3.无状态 4.无/短链接
根据第三条无状态特性,我们可以知道,HTTP协议是无法确认用户情况的,让服务端知道当前用户只有一种情况,携带用户名和密码(身份标识)
cookie🍪:服务端让客户端端保存的数据(存储在客户端上的用户信息数据)
该方法满足了服务端确认用户的的状态,但是问题来了,cookie会将数据明文保存,其安全性就非常的差,session就来了
ession:服务端保存用户数据产生对应的密匙,并告知客户端(存储在服务端的的密匙)
用户登录成功后,如果需要保存cookie,服务端会生成一个随机的字符串,返还给客户端;之后客户端每次发送请求都会携带该随机的字符串;服务端会使用该随机的字符串去做对比,校验有对应关系的用户数据。
1.session的工作必须依赖于cookie
2.客户端也有权拒绝保存数据
django操作cookie
# 视图函数返回值
return HttpResonse()
return render()
return redirect()
...
不直接返回对象 而是先用变量名指代 然后操作对象方法
res = HttpResonse()
return res
res = render()
return res
res = redirect()
return res
# 基本使用
res.set_cookie() # 设置
res.COOKIE.get() # 获取
# 有很多视图函数需要添加登录认证 有时候又需要取消登录认证
装饰器
# 用户登录之后跳转到用户登录之前想要访问的页面
提示:利用url问号携带参数 尝试编写 今日作业!!!

浙公网安备 33010602011771号