django 之 form组件
注册页面
def reg(request): errors = { 'username':'', 'password':''} if request.method == 'POST': username = request.POST.get('username') password = request.POST.get('password') if 'sb' in username: errors['username'] = '用户名不能有sb' if password == '123': errors['password'] = '密码过于简单,请重新设置' return render(request, 'reg.html', locals())
1. django form组件三个功能
渲染标签
校验数据展示信息前端初步校验,可以不做,后端必须校验 !!!2. 校验数据
第一步:建立form类
第二步:实例化产生form对象
第三步:查看该对象form_obj的信息
form_obj.is_valid() 校验是否有效:所有字段验证通过,返回Trueform_obj.errors 错误信息提示:所有未通过校验的字段及错误提示form_obj.cleaned_data 校验通过的数据
form组件校验数据规则:
从上往下依次取值校验
校验通过的数据,放入cleaned_data校验未通过数据,放入errors,当全部通过,errors清空多传入的数据,不会处理form中所有字段默认必须传值(required=True)类中字段基本校验全部通过后,需进行进一步的校验:钩子函数
局部钩子函数:单个字段校验
全局钩子函数:多个字段校验
from django.core.exceptions import ValidationError class MyForm(forms.Form): ..... def clean_name(self): # 局部钩子 name = self.cleaned_data.get('name') if '666' in name: # 1.主动抛异常 raise ValidationError('光喊666是不行的') # 2.自定义异常 self.add_error('name', '光喊666是不行的') return name # 为兼容性考虑,加上return def clean(self): # 全局钩子 password = self.cleaned_data.get('password') confirm_password = self.cleaned_data.get('confirm_password') if not password == confirm_password: self.add_error('confirm_password', '两次密码不一致!!') return self.cleaned_data
前端取消校验:
form标签,添加novalidate属性
右键检查,Elements里面直接修改
3. 渲染标签
from django import formsclass MyForm(forms.Form): name = forms.CharField(max_length=6) password = forms.CharField(max_length=8, min_length=3) email = forms.EmailField()
第一种渲染方式:
封装程度高,扩展性差,用于测试方便快捷
def reg(request): form_obj = MyForm() # 生成一个空对象 return render(request, 'reg.html', locals())
第一种渲染方式
{ { form_obj.as_p }}{ { form_obj.as_ul }}
第二种渲染方式
只渲染获取用户输入的input框,其他提交按钮等需要手动添加
from django import formsclass MyForm(forms.Form): name = forms.CharField(max_length=6, label='用户名') password = forms.CharField(max_length=8, min_length=3) email = forms.EmailField()def reg(request): form_obj = MyForm() # 生成一个空对象 return render(request, 'reg.html', locals())
第二种渲染方式
第三种渲染方式
第三种渲染方式
4. 展示信息
form组件提交数据如果数据不合法,页面上会保留之前用户输入的信息在使用form组件对模型表进行数据校验的时候,只需要保证字段一致在创建的对象的时候直接**form_obj.cleaned_data
提示错误信息时:
{ { foo.errors }} 结果为列表,格式为ul
{ { foo.errors.0 }}取出结果,变为正常格式
5. 常用字段
initial 初始值
error_messages 重写错误信息
Password 隐藏input框密码
radioSelect 圆形点,单选,单radio值为字符串
Select 单选框
SelectMultiple 多选框
CheckBox 方形勾,单选
CheckboxSelectMultiple 方形勾,多选
应用实例
from django import formsfrom django.forms import widgetsclass MyForm(forms.Form): # 按照form组件写一个类 name = forms.CharField(max_length=6, label='用户名', error_messages={ 'max_length': '用户名最长6位', 'required': '用户名不能为空', }) password = forms.CharField(max_length=8, min_length=3, error_messages={ 'max_length': '密码最长6位', 'min_length': '密码最少3位', 'required': '密码不能为空', }, widget=widgets.PasswordInput(attrs={ 'class': 'c1 form-control'})) # attrs 设置标签样式 confirm_password = forms.CharField(max_length=8, min_length=3, error_messages={ 'max_length': '确认密码最长6位', 'min_length': '确认密码最少3位', 'required': '确认密码不能为空', }, widget=widgets.PasswordInput(attrs={ 'class': 'form-control'})) gender = forms.ChoiceField( choices=((1, '男'), (2, '女'), (3, '保密')), label='性别', initial=3, widget=forms.widgets.RadioSelect() ) hobby = forms.ChoiceField( choices=((1, '篮球'), (2, '足球'), (3, '双色球')), label='爱好', initial=3, # 默认值 widget=forms.widgets.Select() # 单选 ) interest = forms.MultipleChoiceField( choices=((1, '看书'), (2, '练字'), (3, '绘画')), label='兴趣', initial=[1, 3], widget=forms.widgets.SelectMultiple() # 多选 ) keep = forms.ChoiceField( label='是否记住密码', initial='checked', widget=forms.widgets.CheckboxInput() ) email = forms.EmailField(error_messages={ 'invalid': '邮箱格式不正确', 'required': '邮箱不能为空' }) keep = forms.ChoiceField( label='是否记住密码', initial='checked', widget=forms.widgets.CheckboxInput() ) def clean_name(self): # 局部钩子 name = self.cleaned_data.get('name') if '666' in name: self.add_error('name', '光喊666是不行的') return name # 为兼容性考虑,加上return def clean(self): # 全局钩子 password = self.cleaned_data.get('password') confirm_password = self.cleaned_data.get('confirm_password') if not password == confirm_password: self.add_error('confirm_password', '两次密码不一致!!') return self.cleaned_data # 使用form组件实现注册方式def reg(request): form_obj = MyForm() # 生成一个空对象 if request.method == 'POST': form_obj = MyForm(request.POST) # 实例化form对象,把post提交的数据直接传入,前后对象名称一致 if form_obj.is_valid(): # 调用form_obj校验数据的方法 models.User.objects.create(**form_obj.cleaned_data) return render(request, 'reg.html', locals())
页面渲染信息
MyForm
django 操作 Cookie,Session
http协议四大特性
1. 基于TCP/IP作用于应用层的协议
2. 基于请求响应
3. 无状态
4. 无链接
cookie,session 即用于保存客户登录状态
cookie:保存在客户端浏览器上的键值对,安全性较差,保存的串一般为服务端识别客户端设置的唯一值(相当于id,<4KB)
session:保存在服务端上的键值对,访问时串相匹配,识别不同用户取出对应私密信息(可以大于4KB)
django 操作 Cookie
服务端产生随机的串儿返回给客户端,服务端将信息存起来('随机字符串':'信息')
将以下?路径设置关掉,网站将失去登录、保存状态的功能
Google浏览器>设置>高级>隐私设置和安全性>网站设置>权限>Cookie>允许网站保存和读取Cookie数据
django视图层函数return的HttpResponse、render、redirect终归为HttpResponse对象:
设置cookie
obj = HttpResponse()obj = render()obj = redirect()# 给浏览器设置cookie,将于此时操作:obj.set_cookie('键','值',expires=超时登录秒) # max_age设置超时登录,IE不能识别,多用expiresreturn obj
获取cookie
request.COOKIES.get('name')request.COOKIES['name']
删除cookie
obj.delete_cookie('值')
应用实例:
1. 没有登录不能访问其他页面,访问时直接跳转到登录页面
2. 装饰器内通过target_path = request.get_full_path()获取用户想访问的路径,给login路径添加get参数login/?next='%s' % target_path
3. login视图函数通过request.GET.get('next')获取用户想访问的路径
from django.conf.urls import urlfrom django.contrib import adminfrom app01 import viewsurlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^home/', views.home), url(r'^reg/', views.reg), url(r'^login/', views.login), url(r'^index/', views.index), url(r'^logout/', views.logout),]
视图层views
from django.shortcuts import render, HttpResponse, redirectdef login(request): if request.method == 'POST': username = request.POST.get('username') password = request.POST.get('password') if username == 'jason' and password == '123': old_path = request.GET.get('next') # 获取原登录目标 if old_path: obj = redirect(old_path) # 登录成功,跳转原目标网页 else: obj = redirect('/home/') # 直接开登录界面,设置home为跳转页面 # 登录成功,给浏览器设置一个cookie obj.set_cookie('name', 'jason', expires=3600*24*7) # 设置超时登录时间,单位为秒 return obj return render(request, 'login.html')def index0(request): if request.COOKIES.get('name'): return HttpResponse('index,登陆可见!!') return redirect('/login/')from functools import wrapsdef login_auth(func): @wraps(func) # 装饰器修复 def inner(request, *args, **kwargs): old_path = request.get_full_path() # 获取验证登录前访问地址 if request.COOKIES.get('name'): # 校验cookie return func(request, *args, **kwargs) return redirect("/login/?next=%s" % old_path) # 携带访问目标地址 return inner@login_authdef index(request): return HttpResponse('index,登陆可见!!')@login_authdef home(request): return HttpResponse('home页面,登录可见!!')@login_authdef reg(request): return HttpResponse('reg页面,登录可见!!')# 删除cookiedef logout(request): rep = redirect('/login/') rep.delete_cookie('name') # 删除用户浏览器上设置的usercookie值 return rep
django 操作 Session
关于session:
django 默认的session存活时间14天 *******
一个浏览器固定占一行session信息,代码中设置多行将会加密到一行中,不影响取值
设置session将会执行三件事:
1. 生成一个随机字符串
2. django表中存储该随机字符串与数据记录:执行后在内存中产生临时缓存,经过SessionMiddleware保存到数据库中
3. 将随机字符串发送给客户端浏览器,浏览器生成一个sessionid键存放session值
取出session时,进过以下步骤:
1. django自动获取浏览器随机字符串,去django session表比对
2. 比对成功,将随机对应的字符串对应的数据,赋值给request.session
3. 通过request.session操作该数据(不存在也不会影响其他代码)
request.session['name'] = 'jason' # 设置 request.session.get('name') #获取 request.session.delete() # 删除当前会话所有Session(数据库) request.session.flush() # 删除当前会话数据及Cookie(数据库、浏览器)
# 获取、设置、删除Session中数据request.session['k1']request.session.get('k1',None)request.session['k1'] = 123request.session.setdefault('k1',123) # 存在则不设置del request.session['k1']# 所有 键、值、键值对request.session.keys()request.session.values()request.session.items()request.session.iterkeys()request.session.itervalues()request.session.iteritems()# 会话session的keyrequest.session.session_key# 将所有Session失效日期小于当前日期的数据删除request.session.clear_expired()# 检查会话session的key在数据库中是否存在request.session.exists("session_key")# 删除当前会话的所有Session数据request.session.delete() # 删除当前的会话数据并删除会话的Cookie。request.session.flush() 这用于确保前面的会话数据不可以再次被用户的浏览器访问 例如,django.contrib.auth.logout() 函数中就会调用它。# 设置会话Session和Cookie的超时时间request.session.set_expiry(value) * 如果value是个整数,session会在些秒数后失效。 * 如果value是个datatime或timedelta,session就会在这个时间后失效。 * 如果value是0,用户关闭浏览器session就会失效。 * 如果value是None,session会依赖全局session失效策略。
设置session的超时时间:
如果value是个整数,session会在些秒数后失效。如果value是个datatime或timedelta,session就会在这个时间后失效。如果value是0,用户关闭浏览器session就会失效。如果value是None,session会依赖全局session失效策略。
request.session.set_expiry(value)
应用实例
from django.conf.urls import urlfrom django.contrib import adminfrom app01 import viewsurlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^set_session/', views.set_session), url(r'^get_session/', views.get_session), url(r'^delete_session/', views.delete_session), url(r'^flush_session/', views.flush_session),]
def set_session(request): request.session['name'] = 'jason' request.session['name1'] = 'egon' request.session['name2'] = 'tank' request.session['name3'] = 'nick' request.session['name4'] = 'sean' return HttpResponse('ok')def get_session(request): print(request.session.get('name')) print(request.session.get('name1')) print(request.session.get('name2')) print(request.session.get('name3')) print(request.session.get('name4')) return HttpResponse('ok')def delete_session(request): request.session.delete() return HttpResponse('ok')def flush_session(request): request.session.flush() return HttpResponse('ok')
设置session时,数据库中的表不存在,将会报错