django form 组件 注册功能 1.渲染前端标签获取用户输入 》》》》》》 渲染标签 2.获取用户输入船体到后端校验 》》》》》》 校验数据 3.校验未通过展示错误信息 》》》》》》》》 展示
django form 组件
注册功能
1.渲染前端标签获取用户输入 》》》》》》 渲染标签
2.获取用户输入船体到后端校验 》》》》》》 校验数据
3.校验未通过展示错误信息 》》》》》》》》 展示信息
校验数据(前后端都可以)
校验前端后端都可以做,但是前端可以不做,后端必须做
django form组件的三大功能
1.渲染标签
2.校验数据
3.展示信息
校验数据:
第一步:写一个form类
from django import forms class MyForm(forms.Form): name = forms.CharField(max_length=6, label="用户名") # 最大为6位,不能超过 password = forms.CharField(max_length=8, min_length=3, label="密码") # 字段不能小于3大于8 email = forms.EmailField(required=False, label="邮箱") # required=False不做校
第二部: 实例化form对象
form_obj = MyForm({"name":"json","password":"123","email":"[email protected]"})
第三部:查看数据校验是否合法
form_obj.is_valid() # 只有所有字段都通过才是True
第四部:查看校验错误的信息
form_obj.errors # 这个放到所有校验未通过的错误信息
第五部:查看通过的信息
form_obj.cleaned_data # 所有校验符合信息
ps: form组件校验数据的规则从上往下一次取值校验
校验通过的放到cleaned_data 中
校验失败的放到form_obj.errors
form 所有字段默认都是必须传值的(required=True),不校验改为false
校验数据时候可以多传,多传的数据不会校验,也不会影响校验结果
渲染标签
form组件只帮你渲染获取用户输入的标签(input),不会帮你渲染提交按钮,需要手动添加
def register(request): # 生成一个空对象,把对象传进去 form_obj = MyForm() return render(request, "register.html", locals()
<h1>第一种渲染方式</h1>
{{ form_obj.name }} {# 只表示name框 #}
{{ form_obj.as_p}} {# 把字段表格框全渲染出来 包括名字
{{ form_obj.as_ul }} {# 把字段表格框全渲染出来 包括名字,但是手写字母是大写
<h1>第二种渲染方式</h1>
<form action=""> <p>{{ form_obj.name.label }}:{{ form_obj.name }}</p> <p>{{ form_obj.password.label }} :{{ form_obj.password }}</p> <p>{{ form_obj.email.label }}:{{ form_obj.email }}</p> <input type="submit" value="确认"> </form>
<h1>第三种渲染</h1> {% for foo in form_obj %} <p>{{ foo.label }}:{{ foo}} </p> {# 把三个框都渲染出来 foo 就像第一种传的方式#}
前端取消校验 <form action="" method="post" novalidate> 只需要加上novalidate,取消校验
form组件提交数据
如果数据不合法,页面上会保留输入数据
在使用form组件对模型表记性数据校验的时候,只需要保证字段一致
那么在创建的对象的时候你就直接**form_obj.cleaned_data
# 把数据添加到数据库
def register(request): # 生成一个空对象,把对象传进去 form_obj = MyForm() if request.method == "POST": print(request.POST) print(request.POST.get("name")) form_obj = MyForm(request.POST) # 现在变成有值的对象 # form_obj注意和if上面一样,重新把对象赋值,如果是错误下面不走,然后返回到前端 if form_obj.is_valid(): print(form_obj.cleaned_data) # {‘name‘: ‘json‘, ‘password‘: ‘666‘, ‘email‘: ‘[email protected]‘} models.User.objects.create(**form_obj.cleaned_data) # 打散后直接创建,不需要挨个获取了 return HttpResponse("ok") return render(request, "register.html", locals())
前端展示错误信息:
<form action="" method="post" novalidate> {% for foo in form_obj %} <p>{{ foo.label }}:{{ foo}} <span>{{ foo.errors.0 }}</span> {# 打印错误信息 #} </p> {# 把三个框都渲染出来 foo 就像第一种传的方式#} {% endfor %} <input type="submit"> </form>
#校验用户,设置条件
class MyForm(forms.Form): name = forms.CharField(max_length=6, label="用户名", error_messages={ "mex_length": "用户名最长六位", "required": "用户名不能为空" }) # 最大为6位,不能超过 password = forms.CharField(max_length=8, min_length=3, label="确认密码") # 字段不能小于3大于8 ,确认密码 confirm_password = forms.CharField(max_length=8, min_length=3, label="密码") # 字段不能小于3大于8 email = forms.EmailField(label="邮箱", error_messages={ "required": "邮箱不能为空", "invalid": "邮箱格式不正确" }) # required=False不做校验
# 钩子函数:
简单说就对于校验通过的字段,再次进行校验
# 局部钩子函数 (单个字段的校验利用局面)
def clean_name(self): name = self.cleaned_data.get("name") if "666" in name: self.add_error("name", "sb666") # 添加错误 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("password", "两次密码不相等") return self.cleaned_data
# 设置标签样式
from django.forms import widgets password = forms.CharField(max_length=8, min_length=3, label="确认密码",widget=widgets.PasswordInput()) 密文 password = forms.CharField(max_length=8, min_length=3, label="确认密码",widget=widgets.PasswordInput(attrs={"class":"form_control c1"})) 样式
#choices字段
gender = forms.ChoiceField( choices=((1, "男"), (2, "女"), (3, "保密")), label="性别", initial=3, # 默认值 widget=forms.widgets.RadioSelect()
cookie
保存在客户端浏览器上的键值对
session
保存在服务端上的键值对
服务端产生随机的串返回给客户端,服务端找一个地方将串与对应的信息存起来(随机字符串:敏感信息)
django
return HttpResponse()
return render()
return redirect()
obj = HttpResponse()
return obj
obj = render()
return obj
obj = redirect()
return obj
cookie使用方法
设置cookie
obj.set_cookie("name","json") # 给浏览器设置cookie
获取cookie
request.COOKIE.get("name")
删除
delete_cookie("user")
删除cookie
def logout(request):
rep = redirect("/login/")
rep.delete_cookie("user") # 删除
return rep
cookie装饰器:
def login_auth(func): @wraps(func) def inner(request, *args, **kwargs): 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 """1.想要登录之前,登录后返回当前你想要的的界面 2.在装饰器上,把自己的路劲记录下来get请求 3.当你登录过后,做一个判断,如果有值直接返回你想返回的界面, 4.如果没有值,直接跳转到主页面""" def index(request): print(request.COOKIES.get("name")) if request.COOKIES.get("name"): return HttpResponse("我是index页面,只有登录才能展示") return redirect("/login/") @login_auth def home(request): return HttpResponse("home.去死吧") @login_auth def nice(request): return HttpResponse("nice,总有刁民想害朕")装饰器
session
设置session
request.session["name"] = "json"
# 1.先生成一个随机的字符串
# 2.在django session表中存储该随机字符串与数据的记录
# 3.将随机的字符串发送给客户端浏览器
获取session
request.session.get("name")
# 1.django自动获取浏览器字符串 取django session表中里面进行比对
# 2. 如果比对成功 会将当前对应的数据赋值给request.session
# 3. 通过request.session 操作该数据(数据不存在,也不会影响业务逻辑)
当后端执行request.session["name"] = "json",会自动把数据存储到数据库中django_session表中,第一个表示随机的串,
第二个是加密后的键值对,第三个是超时时间默认14天, 浏览器会设置一个键为sessionid来存放session值,只要服务端设置成功,浏览器
也会自动保存
ps:传给客户端的是session值是表中第一个数据,然后进行比对,看是否登录
django默认的session存活的时间是两周14天
一个浏览器占一行
# 删除当前会话的所有Session数据(删除数据库中)
request.session.delete()
# 删除当前的会话数据并删除会话的Cookie。(删除两边的)
request.session.flush()
# 设置会话Session和Cookie的超时时间
request.session.set_expiry(value)
* 如果value是个整数,session会在些秒数后失效。
* 如果value是个datatime或timedelta,session就会在这个时间后失效。
* 如果value是0,用户关闭浏览器session就会失效。
* 如果value是None,session会依赖全局session失效策略。
CBV加装饰器
from django.utils.decorators import method_decorator # 类装饰器 # @method_decorator(login_auth, name="get") # 第二种方法 class MyHome(View): @method_decorator(login_auth) # 第三种方法 get和post都会被装饰 def dispatch(self, request, *args, **kwargs): super().dispatch(request, *args, **kwargs) # @method_decorator(login_auth) # 第一种方法 def get(self, request): return HttpResponse("get") def post(self, request): return HttpResponse("post")