forms组件
form组件能够完成的事情:
1.渲染html代码
2.检验数据
3.展示提示信息
class MyForm(forms.Form):username = forms.CharField(min_length=3,max_length=8,label='用户名',error_messages={'min_length':'用户名最少3位','max_length':"用户名最多8位",'required':'用户名不能为空'})#最小3位,最大8位password = forms.CharField(min_length=3,max_length=8,label='密码',error_messages={'min_length': '密码最少3位','max_length': "密码最多8位",'required': '密码不能为空'})email = forms.EmailField(label='邮箱',error_messages={'invalid':'邮箱格式不正确','required':'邮箱不能为空',})#必须符合邮箱格式
校验数据
form_obj = views.MyForm({'username':'wyy','password':'123','email':'123'})form_obj.is_valid() 查看是否符合Falseform_obj.errors 查看不符合数据{'email': ['Enter a valid email address.']}form_obj.cleaned_data 查看符合数据{'username': 'wyy', 'password': '123'}多传不影响校验class内默认都要传值
渲染标签
forms组件只会渲染获取用户输入的标签,不会渲染按钮
后端def index(request):form_obj = MyForm()return render(request,'index.html',locals())前端<p>第一种渲染方式</p> 封装程度高,不利于拓展{{ form_obj.as_p }}{{ form_obj.as_ul }}{{ form_obj.as_table }}<p>第二种渲染方式</p> 可拓展性强,要写的代码多{{ form_obj.username.label }}{{ form_obj.username }}<p>第三种渲染方式</p>{% for form in form_obj %}<p>{{ form.label }}:{{ form }}</p>{% endfor %}
展示信息
后端def index(request):form_obj = MyForm()if request.method == 'POST':form_obj = MyForm(request.POST)if form_obj.is_valid():passreturn render(request,'index.html',locals())前端{% for form in form_obj %}<p>{{ form.label }}:{{ form }}<span style="color: crimson">{{ form.errors.0 }}</span></p>{% endfor %}<input type="submit">必备:get和post请求传给html的对象变量名必须一致数据不合法的时候会保留数据,可以基于之前的进行修改
钩子函数(HOOK)
局部钩子:给单个字段增加检验规则时候可以使用
全部钩子:给多个字段增加检验规则时候可以使用
class MyForm(forms.Form):username = forms.CharField(min_length=3,max_length=8,label='用户名',error_messages={'min_length':'用户名最少3位','max_length':"用户名最多8位",'required':'用户名不能为空'})#最小3位,最大8位password = forms.CharField(min_length=3,max_length=8,label='密码',error_messages={'min_length': '密码最少3位','max_length': "密码最多8位",'required': '密码不能为空'})confirm_password = forms.CharField(min_length=3, max_length=8, label='确认密码',error_messages={'min_length': '确认密码最少3位','max_length': "确认密码最多8位",'required': '确认密码不能为空'})email = forms.EmailField(label='邮箱',error_messages={'invalid':'邮箱格式不正确','required':'邮箱不能为空',})#必须符合邮箱格式#局部钩子def clean_username(self):username = self.cleaned_data.get('username')if 'qqq' in username:#错误信息self.add_error('username','错误信息')#将钩子函数拿到的数据放回去return username#全局钩子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
其他参数
label 字段名error_messages 自定义报错信息initial 默认值required 控制字段是否必填widget = forms.widgets.TextInput(attrs={'class':'form-control'})正则校验from django.core.validators import RegexValidatorphone= forms.CharField(validators=[RegexValidator(r'^[0-9]+$', '请输入数字'),RegexValidator(r'^159[0-9]+$', '数字必须以159开头')],)
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())单选Selectclass LoginForm(forms.Form):...hobby = forms.ChoiceField(choices=((1, "篮球"), (2, "足球"), (3, "双色球"), ),label="爱好",initial=3,widget=forms.widgets.Select())多选Selectclass LoginForm(forms.Form):...hobby = forms.MultipleChoiceField(choices=((1, "篮球"), (2, "足球"), (3, "双色球"), ),label="爱好",initial=[1, 3],widget=forms.widgets.SelectMultiple())单选checkboxclass LoginForm(forms.Form):...keep = forms.ChoiceField(label="是否记住密码",initial="checked",widget=forms.widgets.CheckboxInput())多选checkboxclass LoginForm(forms.Form):...hobby = forms.MultipleChoiceField(choices=((1, "篮球"), (2, "足球"), (3, "双色球"),),label="爱好",initial=[1, 3],widget=forms.widgets.CheckboxSelectMultiple())
Cookie与Session组件
cookie是保存在客户端浏览器上的信息
session是保存在服务端上的信息
session是基于cookie工作的
cookie操作
# 校验登陆是否登陆装饰器def login_auth(func):def inner(request, *args, **kwargs):#获取url(路由+?后数据)target_url = request.get_full_path()#获取cookieif request.COOKIES.get('username'):res = func(request, *args, **kwargs)return reselse:#将上一次访问的页面URL传值给loginreturn redirect('/login/?next=%s' % target_url)return innerdef login(request):if request.method == 'POST':username = request.POST.get('username')password = request.POST.get('password')if username == 'wyy' and password == '123':target_url = request.GET.get('next')if target_url:obj = redirect(target_url)else:obj = redirect('/home/')#设置cookie.时长10分钟,针对IE浏览器需要用expires参数设置时长obj.set_cookie('username', 'wyy',max_age=600,)obj.set_cookie('username', 'wyy',expires=600,)return objreturn render(request, 'login.html')@login_authdef home(request):return HttpResponse('home页面')@login_authdef index(request):return HttpResponse('index页面')@login_authdef test(request):return HttpResponse('test页面')#注销功能@login_authdef logout(request):obj = redirect('/login/')obj.delete_cookie('username')return obj
session操作
默认情况下,需要django_session表,django默认过期时间14天
同一计算机同一浏览器在django_session中一条数据,不同浏览器不同数据,为了节省服务端资源
django_session过期的数据会自动清除
#设置sessiondef set_session(request):request.session['hobby'] = 'girl'request.session.set_expiry() #参数:整数--秒 日期对象--指定日期过期 0--当前浏览器则失效 不写-- django默认失效时间return HttpResponse('session')"""1.自动生成随机字符串2.自动存储到django_session中3.将随机字符串返回给浏览器"""#获取sessiondef get_session(request):request.session.get('hobby')"""1.自动获取sessionid对应的随机字符串2.自动前往django_session中匹配3. 匹配上了则以字典的形式封装到request.session中没有则返回NONE"""#清除sessiondef del_session(request):request.session.delete() #删除服务端sessionrequest.session.flush() #删除客户端与服务端session
session登陆验证
from functools import wrapsdef check_login(func):@wraps(func)def inner(request, *args, **kwargs):next_url = request.get_full_path()if request.session.get("user"):return func(request, *args, **kwargs)else:return redirect("/login/?next={}".format(next_url))return innerdef login(request):if request.method == "POST":user = request.POST.get("user")pwd = request.POST.get("pwd")if user == "alex" and pwd == "alex1234":# 设置sessionrequest.session["user"] = user# 获取跳到登陆页面之前的URLnext_url = request.GET.get("next")# 如果有,就跳转回登陆之前的URLif next_url:return redirect(next_url)# 否则默认跳转到index页面else:return redirect("/index/")return render(request, "login.html")@check_logindef logout(request):# 删除所有当前请求相关的sessionrequest.session.delete()return redirect("/login/")@check_logindef index(request):current_user = request.session.get("user", None)return render(request, "index.html", {"user": current_user})
CBV内方法加装饰器
# CBV内方法加装饰器from django.views import Viewfrom django.utils.decorators import method_decorator# @method_decorator(login_auth,name='get') 方式二,可以叠加多个class Mylogin(View):# @method_decorator(login_auth) 方式三,直接作用于类内所有方法# def dispatch(self, request, *args, **kwargs):# pass# @method_decorator(login_auth) 方式一def get(self):return HttpResponse('get请求')def post(self):return HttpResponse('post请求')
