Django之form组件!
Posted sima-3
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Django之form组件!相关的知识,希望对你有一定的参考价值。
一.手动实现注册功能
注册功能 1.渲染前端标签获取用户输入 >>> 渲染标签 2.获取用户输入传递到后端校验 >>> 校验数据 3.校验未通过展示错误信息 >>> 展示信息 校验数据(前后端都可以校验) 校验前端后端都可以做,但是前端可以不做,后端必须得做!!!
后端:
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‘]=‘user is not valid‘ if password == ‘123‘: errors[‘password‘]=‘too easy‘ return render(request,‘reg.html‘,locals())
前端:
<body> <h1>注册页面</h1> <form action="" method="post"> <p>username: <input type="text" name="username"> <span> errors.username </span> </p> <p>password: <input type="password" name="password"> <span> errors.password </span> </p> <input type="submit"> </form> </body>
效果:
二. django form组件
1.渲染标签 2.校验数据 3.展示信息
1.校验数据:
测试小技巧:
第一步需要一个form类 from django import forms class MyForm(forms.Form): name = forms.CharField(max_length=6) password = forms.CharField(max_length=8,min_length=3) email = forms.EmailField(required=True) 第二步实例化form对象 from app01 import views form_obj=views.MyForm(‘name‘:‘jasonhaha‘,‘password‘:‘12‘,‘email‘:‘123‘) 第三步查看数据校验是否合法 form_obj.is_valid() # 只有当所有的字段都校验通过才会返回True 第四步查看校验错误的信息 form_obj.errors # 这个里面放的是所有校验未通过的字段及错误提示 """ ‘name‘: [‘Ensure this value has at most 6 characters (it has 7).‘], ‘password‘: [‘Ensure this value has at least 3 characters (it has 2).‘], ‘email‘: [‘Enter a valid email address.‘] """ 第五步查看校验通过的数据 form_obj.cleaned_data # 符合校验规则数据都会被放到该对象中 ps:form组件校验数据的规则从上往下依次取值校验 校验通过的放到cleaned_data 校验失败的放到errors
注意:
form中所有的字段默认都是必须传值的(required=True),不想传可以改成False
校验数据的时候可以都传(多传的数据不会做任何的校验>>>不会影响form校验规则)
2.渲染标签:
后端:
from django import forms class MyForm(forms.Form): name = forms.CharField(max_length=6,label=‘用户名‘)
#不写label,则在前端显示的是Name password = forms.CharField(max_length=8,min_length=3) email=forms.EmailField(required=False) def reg(request): form_obj = MyForm() render(request,‘reg.html‘,locals())
前端:
form组件只帮你渲染获取用户输入的标签,不会帮你渲染提交按钮,需要手动添加 <h1>第一种渲染方式(可扩展性较差)</h1> form_obj.as_p form_obj.as_ul
<input type="submit">
<h1>第二种渲染方式</h1> <form action=""> <p> form_obj.name.label form_obj.name </p>
#label可标识前面的注释 <p> form_obj.password.label form_obj.password </p> <p> form_obj.email.label form_obj.email </p> <input type="submit"> </form>
<h1>第三种渲染标签的方式</h1> <form action=""> % for foo in form_obj % <p> foo.label foo </p> % endfor %
<input type="submit">
</form>
前端取消校验:
<form action="" method="post" novalidate> </form>
3.form组件前后端综合使用
后端:
from django import forms class MyForm(forms.Form): name = forms.CharField(max_length=6) password = forms.CharField(max_length=8,min_length=3) email=forms.EmailField(required=True) def reg(request): form_obj = MyForm() if request.method == ‘POST‘: print(request.POST) form_obj = MyForm(request.POST) if form_obj.is_valid(): return HttpResponse(‘ok‘) return render(request,‘reg.html‘,locals())
前端:
<h1>第三种渲染标签的方式</h1> <form action="" method="post" novalidate> % for foo in form_obj % #foo是每一个输入框对象 <p> foo.label foo <span> foo.errors.0 </span> </p> % endfor % <input type="submit">
form组件提交数据如果数据不合法,页面上会保留之前用户输入的信息
效果:
错误提示可以自定义成中文:
class MyForm(forms.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‘: ‘密码最长8位‘, ‘required‘: ‘密码不能为空‘, ‘min_length‘:‘密码最少3位‘ email = forms.EmailField(error_messages= ‘invalid‘:‘邮箱格式不正确‘, ‘required‘:‘邮箱不能为空‘ )
效果:
4.把注册信息写入数据库:
models.py:
from django.db import models # Create your models here. class User(models.Model): name = models.CharField(max_length=32) password = models.CharField(max_length=32) email = models.EmailField()
后端:
def reg(request): form_obj = MyForm() if request.method == ‘POST‘: print(request.POST) form_obj = MyForm(request.POST) if form_obj.is_valid(): data=form_obj.cleaned_data models.User.objects.create(**data) return render(request,‘reg.html‘,locals())
ps:
在使用form组件对模型表进行数据校验的时候,只需要保证字段一致
那么在创建的对象的时候,把校验通过后的字典键值对拿过来,就直接**form_obj.cleaned_data
效果:
三. form 钩子函数
# 局部钩子函数 (单个字段的校验利用局部钩子函数) 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‘,"两次密码不一致,你这个dsb!") return self.cleaned_data
四. forms.widgets的相关用法(可设置标签样式)
class MyForm(forms.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‘: ‘密码最长8位‘, ‘required‘: ‘密码不能为空‘, ‘min_length‘:‘密码最少3位‘ ,widget=widgets.PasswordInput(attrs=‘class‘:‘c1 form-control‘)) confirm_password = forms.CharField(max_length=8, min_length=3, error_messages= ‘max_length‘: ‘确认密码最长8位‘, ‘required‘: ‘确认密码不能为空‘, ‘min_length‘: ‘确认密码最少3位‘ ,widget=widgets.PasswordInput()) email = forms.EmailField(error_messages= ‘invalid‘:‘邮箱格式不正确‘, ‘required‘:‘邮箱不能为空‘ ) 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() ) hobby1 = forms.MultipleChoiceField( choices=((1, "篮球"), (2, "足球"), (3, "双色球"),), label="爱好", initial=[1, 3], widget=forms.widgets.SelectMultiple() ) keep = forms.ChoiceField( label="是否记住密码", initial="checked", widget=forms.widgets.CheckboxInput() )
效果:
五.django操作cookie,session
http协议四大特性 1.基于TCP/IP作用于应用层的协议 2.基于请求响应 3.无状态 4.无连接 cookie 保存在客户端浏览器上的键值对 session 保存在服务端上的键值对 服务端产生随机的串儿返回给客户端,服务端找一个地方将串儿与对应的信息存起来‘随机字符串‘:‘敏感信息‘
1.cookie:
django return HttpResponse() return render() return redirect() obj = HttpResponse() return obj obj = render() return obj obj = redirect() return obj 设置cookie obj.set_cookie() # 给浏览器设置cookie 获取cookie request.COOKIE.get(‘name‘) request.COOKIE[‘name‘]
cookie版登录认证:
def 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/‘) # 用户登录成功 朝浏览器设置一个cookie # obj.set_cookie(‘name‘,‘jason‘,expires=7*24*3600) # obj.set_cookie(‘name‘,‘jason‘,max_age=5)
注释:cookie生命周期为5s obj.set_cookie(‘name‘,‘jason‘) return obj return render(request,‘login.html‘) from functools import wraps def login_auth(func): @wraps(func) def inner(request,*args,**kwargs): # 校验cookie # print(request.get_full_path()) old_path = request.get_full_path() if request.COOKIES.get(‘name‘): return func(request,*args,**kwargs) return redirect(‘/login/?next=%s‘%old_path) return inner @login_auth def index(request): print(request.COOKIES.get(‘name‘)) # if request.COOKIES.get(‘name‘): return HttpResponse(‘我是index页面,只有登录了才能看‘) @login_auth def home(request): return HttpResponse(‘我是home页面,只有登录了才能看‘) @login_auth def xxx(request): return HttpResponse(‘我是xxx页面,只有登录了才能看‘) def logout(request): rep = redirect("/login/") rep.delete_cookie("user") # 删除用户浏览器上之前设置的usercookie值 return rep
2.session:
设置session request.session[‘name‘] = ‘jason‘ # 1.先生成一个随机的字符串 # 2.在django session表中存储该随机字符串与数据的记录 # 3.将随机的字符串发送给客户端浏览器 获取session request.session.get(‘name‘) # 1.django自动获取浏览器随机字符串取django session表里面比对 # 2.如果比对成功 会将当前随机字符串对应的数据赋值给request.session # 3.通过request.session操作该数据(数据不存在也不会影响我们的业务逻辑)
django默认的session存活时间是两周(14天),每个浏览器只有一条数据:
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‘)
浏览器会设置一个键为sessionid来存放session值 # 删除当前会话的所有Session数据 request.session.delete() # 删除当前的会话数据并删除会话的Cookie。 request.session.flush() 这用于确保前面的会话数据不可以再次被用户的浏览器访问 例如,django.contrib.auth.logout() 函数中就会调用它。
浏览器会设置一个键为sessionid来存放session值 # 删除当前会话的所有Session数据 request.session.delete() # 删除当前的会话数据并删除会话的Cookie。 request.session.flush() 这用于确保前面的会话数据不可以再次被用户的浏览器访问 例如,django.contrib.auth.logout() 函数中就会调用它。
session版登录认证:
from functools import wraps def 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 inner def login(request): if request.method == "POST": user = request.POST.get("user") pwd = request.POST.get("pwd") if user == "alex" and pwd == "alex1234": # 设置session request.session["user"] = user # 获取跳到登陆页面之前的URL next_url = request.GET.get("next") # 如果有,就跳转回登陆之前的URL if next_url: return redirect(next_url) # 否则默认跳转到index页面 else: return redirect("/index/") return render(request, "login.html") @check_login def logout(request): # 删除所有当前请求相关的session request.session.delete() return redirect("/login/") @check_login def index(request): current_user = request.session.get("user", None) return render(request, "index.html", "user": current_user)
以上是关于Django之form组件!的主要内容,如果未能解决你的问题,请参考以下文章