forms组件钩子函数
钩子函数可以让字段在原有的校验功能上在新增一个自定义校验的功能。
局部钩子
校验单个字段,在form类中编写一个函数:
def clean_字段名(self):
校验代码
return 字段值
比如:判断用户名name字段值是否存在:
class LoginForm(forms.Form):
name = forms.CharField(max_length=8)
def clean_name(self):
# 先获取字段值
name = self.clean_data.get('name')
# 判断是否存在
is_exist = models.User.objects.filter(name=name)
if is_exist:
# 错误信息展示
self.add_error('name', '用户名已存在')
# 最后将你勾上来的name返回回去
return name
全局钩子
校验多个字段,在form类中编写一个函数:
def clean(self):
校验代码
return self.cleaned_data
比如校验两个字段值是否一致:
class LoginForm(forms.Form):
name = forms.CharField(max_length=8)
confirm_name = forms.CharField(max_length=8)
def clean(self):
# 先获取字段值
name = self.clean_data.get('name')
confirm_name = self.clean_data.get('confirm_name')
# 判断是否一致
if name != confirm_name:
# 错误信息展示
self.add_error('confirm_name', '两次用户名不一致')
# 最后将整个数据返回
return self.clean_data
forms组件字段参数
字段参数
validators详解
演示:
from django.core.validators import RegexValidator
class MyForm(forms.Form):
phone = forms.CharField(
validators=[
RegexValidator(r'^[0-9]+$', '请输入数字'),
RegexValidator(r'^159[0-9]+$', '数字必须以159开头')
]
)
choices详解
定义选择类型的标签内部对应关系,可以直接编写,也可以从数据库中获取。
方式一:
# 直接编写
class MyForm(forms.Form):
gender = forms.fields.ChoiceField(
choices=((1, "男"), (2, "女"), (3, "保密")),
label="性别",
)
# 数据库获取数据
class MyForm(forms.Form):
course = forms.fields.ChoiceField(
choices=models.Course.objects.all().values_list('id', 'name'),
label="课程",
)
方式二:
# 直接编写
class MyForm(forms.Form):
gender = forms.fields.ChoiceField(label="性别")
def __init__(self, *args, **kwargs):
super(MyForm, self).__init__(*args, **kwargs)
self.fields['gender'].choices = ((1, "男"), (2, "女"), (3, "保密"))
# 数据库获取数据
class MyForm(forms.Form):
course = forms.fields.ChoiceField(label="课程")
def __init__(self, *args, **kwargs):
super(MyForm, self).__init__(*args, **kwargs)
self.fields['course'].choices = models.Course.objects.all().values_list('id', 'name')
widget详解
使用form组件生成的标签无法在前端自定义样式,只能使用widget来控制。
基本语法:
widgets=forms.widgets.控制type的类型(
attrs={'属性1':'值',...}
)
比如:
class MyForm(forms.Form):
name = forms.CharField(
widget=forms.widgets.TextInput(
attr={'class':'c1'}
)
)
文本输入框
widget=forms.widgets.TextInput()
密码输入框
widget=forms.widgets.PasswordInput()
数字输入框
widget=forms.widgets.NumberInput()
radio
class MyForm(forms.Form):
gender = forms.fields.ChoiceField(
choices=((1, "男"), (2, "女"), (3, "保密")),
label="性别",
widget=forms.widgets.RadioSelect()
)
单选select
class MyForm(forms.Form):
gender = forms.fields.ChoiceField(
choices=((1, "男"), (2, "女"), (3, "保密")),
label="性别",
widget=forms.widgets.Select()
)
多选select
class MyForm(forms.Form):
hobby = forms.fields.MultipleChoiceField(
choices=((1, "read"), (2, "run"), (3, "game")),
label="爱好",
widget=forms.widgets.SelectMultiple()
)
单选checkbox
class MyForm(forms.Form):
keep = forms.ChoiceField(
label="是否记住密码",
widget=forms.widgets.CheckboxInput()
)
多选checkbox
class MyForm(forms.Form):
hobby = forms.fields.MultipleChoiceField(
choices=((1, "read"), (2, "run"), (3, "game")),
label="爱好",
widget=forms.widgets.CheckboxSelectMultiple()
)
forms组件字段类型
常见字段
其他字段
ModelForm简单使用
forms组件主要配合models里面的模型类一起使用,但是模型类里面的字段需要在forms类中相当于重写一遍,代码冗余,为了更好的结合forms与models的关系,有了一个ModelForm(基于forms组件)。
简单使用
models:
class User(models.Model):
name = models.CharField(max_length=32)
age = models.IntegerField()
addr = models.CharField(max_length=32)
forms:
class MyUser(forms.ModelForm):
class Meta:
model = models.User # 指定关联的表
fields = '__all__' # 所有的字段全部生成对应的forms字段
labels = { # 每个字段标签的labels参数
'name': '用户名',
'age': '年龄',
'addr': '地址'
}
widgets = { # 每个字段标签的widget参数
"name": forms.widgets.TextInput(attrs={"class": "form-control"}),
}
views:
添加数据
def home(request):
form_obj = MyUser()
if request.method == 'POST':
if form_obj.is_valid():
# 获取提交的数据
form_obj = MyUser(request.POST)
# 保存数据,向表中添加数据
form_obj.save()
return render(request, 'home.html', locals())
编辑数据
def home(request):
form_obj = MyUser()
if request.method == 'POST':
if form_obj.is_valid():
# 获取数据看看是否已存在
edit_obj = models.User.objects.filter(name=request.POST.get('name')).first()
# 新增还是保存就取决于instance参数有没有值
form_obj = MyUser(request.POST,instance=edit_obj)
# 保存数据
form_obj.save()
return render(request, 'home.html', locals())
cookie与session简介
cookie
简介
HTTP协议中有一个特性:无状态,意思是服务端不会保存客户端的数据,客户端一直向服务端发送请求,服务端都不会认识客户端,而cookie就可以让服务端认识客户端。
cookie具体指的是一段小信息,它是服务器发送出来存储在浏览器上的一组组键值对,下次访问服务器时浏览器会自动携带这些键值对,以便服务器提取有用信息。
比如在一些网站中,你登陆后就不需要在登录了,这就是因为你的信息被保存在了cookie中,登录一次后,那些网站就知道你已经登录了。
原理
由服务器产生内容,浏览器收到后保存在cookie;当浏览器再次访问时,浏览器会自动带上cookie,这样服务器就能通过cookie的内容来判断这个是“谁”了。
session
简介
如果数据保存在cookie中,很容易被看到,安全性太低,因此需要一个新东西,那就是session。它把数据保存在了服务端,并给客户端返回一个随机字符串保存,这个随机字符串与服务端里的数据对应。每次客户端发送请求时会携带该随机字符串,服务端会进行比对。
django操作cookie
基本使用
设置cookie
def index(request):
res = HttpResponse('index页面')
res.set_cookie('name', 'abcd')
return res
获取cookie
def home(request):
if request.COOKIE.get('name'):
return HttpResponse('cookie有name')
return HttpResponse('cookie中没有name')
进阶
在上述例子中,如果我想要给多个视图函数添加一个判断cookie的功能,我们可以使用装饰器:
def login_auth(func):
def inner(request, *args, **kwargs):
if request.COOKIES.get('name'):
return func(request, *args, **kwargs)
return HttpResponse('你的cookie中还没有name')
return inner