博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Python Django 多对多三种创建方式 form组件 cookie和session
阅读量:4658 次
发布时间:2019-06-09

本文共 12678 字,大约阅读时间需要 42 分钟。

一 表中多对多关系三种创建方式

以Book表和Author表多对多关系例

1.第一种方式:全自动(推荐使用):models.ManyToManyField(to='类名')优点:不需要你手动创建第三张表缺点:第三张表不是你手动创建的,字段是固定的无法拓展class Book(models.Model):    title = models.CharField(max_length=32)    price = models.DecimalField(max_digits=8,decimal_places=2)    # 创建多对多外键字段        authors = models.ManyToManyField(to='Author')class Author(models.Model):    name = models.CharField(max_length=32)2.第二种方式:手动创建第三张表(了解即可)优点:第三张表可以任意拓展字段缺点:orm 查询不方便class Book(models.Model):    title = models.CharField(max_length=32)    price = models.DecimalField(max_digits=8,decimal_places=2)class Author(models.Model):    name = models.CharField(max_length=32)# 第三张表class Book2Author(models.Model):    book = models.ForeignKey(to='Book')    author = models.ForeignKey(to='Author')    create_time = models.DateField(auto_now_add=True)3.第三种方式:半自动(推荐使用******)优点:结合自动和手动优点 ps:多对多字段不支持增删改查:add(),remove(),set(),clear()class Book(models.Model):    title = models.CharField(max_length=32)    price = models.DecimalField(max_digits=8,decimal_places=2)    authors = models.ManyToManyField(to='Author',through='Book2Author',through_fields=('book','author'))    # through 告诉django orm 书籍表和作者表的多对多关系是通过Book2Author来记录的    # through_fields 告诉django orm记录关系时用过Book2Author表中的book字段和author字段来记录的                """                多对多字段的                add                set                remove                clear不支持                """class Author(models.Model):    name = models.CharField(max_length=32)    # books = models.ManyToManyField(to='Book', through='Book2Author', through_fields=('author', 'book'))class Book2Author(models.Model):    book = models.ForeignKey(to='Book')    author = models.ForeignKey(to='Author')    create_time = models.DateField(auto_now_add=True)

form组件

form组件的三大功能

  #1.数据检验  #2.渲染页面  #3.展示信息

1.form组件的基本用法

##校验数据

#1.首先在views.py中写一个基础了forms.Form的类(定义与模型表的定义相似)
from django import forms from django.forms import widgets from app01 import models class MyRegForm(forms.Form):     username = forms.CharField(max_length=8, min_length=3, label='用户名',                                error_messages={
'max_length': '用户名最大八位', 'min_length': '用户名最小三位', 'required': '用户名不能为空' }, widget=widgets.TextInput(attrs={'class': 'form-control'}) )
 

 

#pycharm自带form组件类测试及语法

 

 

 测试语法总结:

from app01 import views1.将需要校验的数据 以字典的方式传递给自定义的类 实例化产生对象:字典传值产生对象form_obj = views.LoginForm({
'username':'jason','password':'123','email':'123'})2.如何查看数据是否全部合法:对象.is_valid()form_obj.is_valid() # 只有所有的数据都符合要求 才会是True 3.如何查看错误原因:对象.errorsform_obj.errors{'password': ['Ensure this value has at least 5 characters (it has 3).'], 'email': ['Enter a valid email address.']}4.如何查看通过校验的数据:对象.cleaned_data form_obj.cleaned_data {
'username': 'jason'}1.校验数据时只要有一个校验通过:对象.is_valid()结果就为false2. 数据校验时会把数据与form组件类中的字段括号内的条件进行对比错误的放进对errors中,正确的放进cleaned_data中3.数据多传不管少传对象.is_valid()结果就为false4.产生对象要以字典形式传值

##前端渲染页面的三种方式

# 后端在一个视图函数中返回html页面并传入form组件类的事例化对象,form组件只帮你渲染获取用户输入的标签,不会帮你渲染提交按钮,需要手动添加# 前端1.第一种方式(下面分别为p标签或ul 和table标签包裹输入框,对象中有几个form字段就有几个inpu框)

第一种渲染页面的方式(封装程度太高 一般只用于本地测试 通常不适用)

{
{ form_obj.as_p }} {
{ form_obj.as_ul }} {
{ form_obj.as_table }}
2.第二种方式:{
{ form_obj.username.label }}为注释

第二种渲染页面的方式(可扩展性较高 书写麻烦)

{

{ form_obj.username.label }}{
{ form_obj.username }}

{

{ form_obj.password.label }}{
{ form_obj.password }}

{

{ form_obj.email.label }}{
{ form_obj.email }}

3.第三种方式:推荐(一个foo相当于一个input框)

第三种渲染页面的方式(推荐)

{
% for foo in form_obj %}

{

{ foo.label }}{
{ foo }}

{
% endfor %}
4.前端取消校验:novalidate
 

##注意

注意事项1.forms组件在帮你渲染页面的时候 只会渲染获取用户输入的标签  提交按钮需要你手动添加                2.input框的label注释  不指定的情况下 默认用的类中字段的首字母大写            3.校验数据的时候可以前后端都校验 做一个双重的校验但是前端的校验可有可无 而后端的校验则必须要有,因为前端的校验可以通过爬虫直接避开前端取消浏览器校验功能form标签指定novalidate属性即可
4.form组件提交数据如果数据不合法,页面上会保留之前用户输入的信息在使用form组件对模型表进行数据校验的时候,只需要保证字段一致那么在创建的对象的时候你就直接**form_obj.cleaned_data例:后端def reg(request): # 生成一个空对象 form_obj = MyForm() if request.method == 'POST': print(request.POST) form_obj = MyForm(request.POST) if form_obj.is_valid(): print(form_obj.cleaned_data) models.User.objects.create(**form_obj.cleaned_data) return render(request,'reg.html',locals())

##展示错误信息

前端:{
{ foo.errors.0 }}
{
% for foo in form_obj %}

{

{ foo.label }}:{
{ foo }} {
{ foo.errors.0 }}

{
% endfor %}
后端:form组件类中:error_messages={k1:v1,k2:v2,...}password = forms.CharField(max_length=8,min_length=5,label='密码',error_messages={
'max_length':'密码最大八位','min_length':'密码最小五位','required':'密码不能为空'})

2.钩子函数

作用:相当于对数据的二次校验,编写在form组件的类中

局部钩子函数:作用于一个字段

局部钩子(针对某一个字段做额外的校验)   校验用户名中不能包含666 一旦包含 提示   def clean_username(self):        username = self.cleaned_data.get('username')        if '666' in username:            # raise ValidationError('奥术大师就卡的凯撒就肯定会')            self.add_error('username','光喊666是不行的 你得自己上')        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

3.form组件类中常用字段和插件

1.初始值,input框里面的初始值:initialclass LoginForm(forms.Form):    username = forms.CharField(        min_length=8,        label="用户名",        initial="张三"  # 设置默认值    )    pwd = forms.CharField(min_length=6, label="密码")2.重写错误信息:error_messagesclass 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="密码")3. 是否必填:required 4.控制标签属性和样式:密码为例,括号中可填样式from django.forms import widgets# 类中字段括号内书写widget=widgets.PasswordInput()widget=widgets.PasswordInput(attrs={
'class':'form-control c1 c2','username':'jason'})5.passwordwidget=widgets.PasswordInput()widget=widgets.PasswordInput(attrs={
'class':'form-control c1 c2','username':'jason'})6.正则from django.core.validators import RegexValidatorclass LoginForm(forms.Form): username = forms.CharField(max_length=8,min_length=3,label='用户名',initial='tankdsb', error_messages={ 'max_length':'用户名最大八位', 'min_length':'用户名最小三位', 'required':'用户名不能为空' },widget=widgets.TextInput() ) # 用户名最长八位最短三位 password = forms.CharField(max_length=8,min_length=5,label='密码',error_messages={ 'max_length':'密码最大八位', 'min_length':'密码最小五位', 'required':'密码不能为空' }, widget=widgets.PasswordInput(attrs={
'class':'form-control c1 c2','username':'jason'}) ) # 密码最长八位最短五位 confirm_password = forms.CharField(max_length=8, min_length=5, label='确认密码', error_messages={ 'max_length': '确认密码最大八位', 'min_length': '确认密码最小五位', 'required': '确认密码不能为空' }, required=False, validators=[RegexValidator(r'^[0-9]+$', '请输入数字'), RegexValidator(r'^159[0-9]+$', '数字必须以159开头')]) # 密码最长八位最短五位 email = forms.EmailField(label='邮箱',error_messages={ 'required':'邮箱不能为空', 'invalid':'邮箱格式不正确' }) # email必须是邮箱格式7.# 单选的radio框 gender = forms.ChoiceField( choices=((1, "男"), (2, "女"), (3, "保密")), label="性别", initial=3, widget=forms.widgets.RadioSelect() ) # 单选select hobby = forms.ChoiceField( choices=((1, "篮球"), (2, "足球"), (3, "双色球"),), label="爱好", initial=3, widget=forms.widgets.Select() ) # 多选的select框 hobby1 = forms.MultipleChoiceField( choices=((1, "篮球"), (2, "足球"), (3, "双色球"),), label="爱好", initial=[1, 3], widget=forms.widgets.SelectMultiple() ) # 单选的checkbox keep = forms.ChoiceField( label="是否记住密码", initial="checked", widget=forms.widgets.CheckboxInput() ) # 多选的checkbox hobby2 = forms.MultipleChoiceField( choices=((1, "篮球"), (2, "足球"), (3, "双色球"),), label="爱好", initial=[1, 3], widget=forms.widgets.CheckboxSelectMultiple() ) phone = forms.CharField( validators=[RegexValidator(r'^[0-9]+$', '请输入数字'), RegexValidator(r'^159[0-9]+$', '数字必须以159开头')], )
View Code

cookie和session

产生背景:由于http协议是无状态的 无法记录用户状态 

cookie:

cookie就是保存在客户端浏览器上的键值对工作原理:当你登陆成功之后 浏览器上会保存一些信息下次再访问的时候 就会带着这些信息去访问服务端  服务端通过这些信息来识别出你的身份            cookie虽然是写在客户端浏览器上的  但是是服务端设置的 浏览器可以选择不服从命令 禁止写cookie

session

session就是保存在服务器上的键值对session虽然是保存在服务器上的键值对但是它是依赖于cookie工作的            服务端返回给浏览器一个随机的字符串浏览器以键值对的形式保存sessionid:随机字符串            浏览器在访问服务端的时候  就会将随机字符串携带上后端获取随机串与后端的记录的做比对随机字符串1:数据1随机字符串2:数据2

1.Cookie的使用

django返回给客户端浏览器的都必须是HttpResponse对象        return HttpResponse()        return render()        return redirect()obj1 = HttpResponse()return obj1obj2 = render()return obj2obj3 = redirect()return obj3基本语法1.设置cookie利用的就是HttpResponse对象:对象.set_cookie('k1','v1')   obj1.set_cookie('k1','v1')2获取cookie   request.COOKIE.get()3.删除cookie  obj1.delete_cookie("k1") 例:
def logout(request):    rep = redirect("/login/")    rep.delete_cookie("user")  # 删除用户浏览器上之前设置的usercookie值    return rep 4.
设置超时时间    max_age=None, 超时时间    expires=None, 超时时间(IE requires expires, so set it if hasn't been already.)

# 装饰器

 
def login_auth(func):     @wraps(func)     def inner(request,*args,**kwargs):         # 从request中获取cookie         # print(request.path)         # print(request.get_full_path())         target_url = request.get_full_path()         if request.COOKIES.get('name'):             res = func(request,*args,**kwargs)             return res         else:             return redirect('/lg/?next=%s'%target_url)     return inner
 
def lg(request):     if request.method == 'POST':         username = request.POST.get('username')         password = request.POST.get('password')         if username == 'jason' and password == '123':             # 先获取url中get请求携带的参数             old_url = request.GET.get('next')             # 判断用户是直接访问的登陆页面 还是从别的页面的调过来             if old_url:                 obj = redirect(old_url)             else:                 # 如果用户直接访问的登陆页面 那么登陆完成之后 直接跳到网站的首页                 obj = redirect('/home/')             obj.set_cookie('name','jason',max_age=30)  # 浏览器上就会保存键值对name:jason             return obj     return render(request,'lg.html')
 

2.Session的使用

# 登录def login(request):    if request.method == 'POST':        name = request.POST.get('name')        pwd = request.POST.get('pwd')        if name == 'jason' and pwd == '123':            request.session['name'] = 'jason'            targer_url = request.GET.get('next')            if targer_url:                return redirect(targer_url)            else:               return HttpResponse('ok')    return render(request,'login.html')# 登录装饰器def login_auth(func):    @wraps(func)    def inner(request,*args,**kwargs):        targe_url = request.get_full_path()        if request.session.get('name'):            res = func(request,*args,**kwargs)            return res        else:            return redirect('/login/?next=%s' % targe_url)    return inner

 

1.设置session:request.session[k] = v request.session['name'] = 'jason'"""上面这一句话发生了三件事  1.django 内部自动生成一个随机字符串  2.将随机字符串和你要保存的数据 写入django_session表中(现在内存中生成一个缓存记录 等到经过中间件的时候才会执行)  3.将产生的随机字符串发送给浏览器写入cookie   sessionid:随机字符串            """2.获取session:request.session.get(k)  request.session.get('name')

获取session

request.session.get('name')
"""
上面这一句话发生了三件事
1.django内部会自动从请求信息中获取到随机字符串
2.拿着随机字符串去django_session表中比对
3.一旦对应上了就将对应的数据解析出来放到request.session中
"""

3.删除# 删除当前会话的所有Session数据   request.session.delete(k)  # 删除的是浏览器的sessionid信息# 删除当前的会话数据并删除会话的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失效策略。

转载于:https://www.cnblogs.com/tfzz/p/11580892.html

你可能感兴趣的文章
寻找最大的数
查看>>
【转】java中float与byte[]的互转 -- 不错
查看>>
sockaddr和sockaddr_in的区别
查看>>
基础练习1
查看>>
左旋转字符串
查看>>
第二次C语言实验报告
查看>>
XPath轴
查看>>
Struts2的优点与Struts1的区别:
查看>>
5-29 删除字符串中的子串
查看>>
webdriver模拟鼠标操作
查看>>
Spring cloud 基础
查看>>
游戏开发Unity渲染场景光照性能优化 ShaderLOD
查看>>
java中构造方法的使用
查看>>
使用Expression动态创建lambda表达式
查看>>
MapReduce
查看>>
找工作——JVM内存管理
查看>>
【Flask】在Flask中使用logger
查看>>
好系统重装助手教你如何让win10系统快速开机
查看>>
linux开机启动
查看>>
BZOJ 1101 [POI2007]Zap 【莫比乌斯反演】
查看>>