zoukankan      html  css  js  c++  java
  • 多对多表三种创建方式,forms组件,cookie与session

    ORM创建多对多三种方式

    第一种(纯自动 推荐使用)
    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)
        addr = models.CharField(max_length=255)
    

    通过虚拟字段创建第三张表

    这种创建方式方便是方便,但是我们不能往第三张表中添加额外字段

    第二种(纯手动 不推荐使用)
    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)
        addr = models.CharField(max_length=255)
    
    
    class Book2Author(models.Model):
        book = models.ForeignKey(to='Book')
        author = models.ForeignKey(to='Author')
        info = models.CharField(max_length=255)
    

    这种创建方式第三张表可拓展性高, 但是ORM操作会比较麻烦,我们正查时, 不可以通过外键字段进行跨表查询

    第三张(半自动 推荐使用)
    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_fields 告诉django orm记录关系时用过Book2Author表中的book字段和author字段来记录的
    # through 告诉django orm 书籍表和作者表的多对多关系是通过Book2Author来记录的
    
    class Author(models.Model):
        name = models.CharField(max_length=32)
        addr = models.CharField(max_length=255)
    
    
    class Book2Author(models.Model):
        book = models.ForeignKey(to='Book')
        author = models.ForeignKey(to='Author')
        info = models.CharField(max_length=255)
    

    半自动既可以在第三张表中添加额外字段,ORM也方便查询

    Book表中的虚拟字段authors中的 'to' 还是代表与Author表建立多对多关联, 'through' 代表通过'Book2Author' 这张表, through_fields中的两个参数,第一个参数表示,第三张表哪个字段可以关联Book表,第二个则是代表哪个字段关联Author表

    注意:
    多对多字段的
    			add
    			set
    			remove
    			clear
                不支持
    因为半自动时,表中可能存在其他外键字段,手动加就完事了
    

    forms组件

    forms组件能够帮你完成下面的操作
    1.渲染前端页面
    2.校验数据是否合法
    3.展示错误信息

    1.forms组件基本使用方法
    from django import forms
    
    
    class LoginForm(forms.Form):
        username = forms.CharField(max_length=8,min_length=3)  # 用户名最长八位最短三位
        password = forms.CharField(max_length=8,min_length=5)  # 密码最长八位最短五位
        email = forms.EmailField()  # email必须是邮箱格式
    
    2.基本使用
    from app01 import views
            1.将需要校验的数据 以字典的方式传递给自定义的类 实例化产生对象
            form_obj = views.LoginForm({'username':'jason','password':'123','email':'123'})
            2.如何查看数据是否全部合法
            form_obj.is_valid()  # 只有所有的数据都符合要求 才会是True
            False
            3.如何查看错误原因
            form_obj.errors
            {
                'password': ['Ensure this value has at least 5 characters (it has 3).'], 
                'email': ['Enter a valid email address.']
            }
            4.如何查看通过校验的数据
            form_obj.cleaned_data  
            {'username': 'jason'}
    

    注意事项:

    1.自定义类中所有的字段默认都是必须要传值的
    2.可以额外传入类中没有定义的字段名 forms组件不会去校验 也就意味着多传一点关系没有
    form_obj = views.LoginForm({'username':'jason','password':'123456','email':'123@qq.com'})
    form_obj.is_valid()
    True
    
    form_obj = views.LoginForm({'username':'jason','password':'123456'})
    form_obj.is_valid()
    False
    
    form_obj = views.LoginForm({'username':'jason','password':'123456','email':'123@qq.com','hobby':'read'})
    form_obj.is_valid()
    True
    
    2.渲染页面

    ​ 三种方式

    <p>第一种渲染页面的方式(封装程度太高 一般只用于本地测试  通常不适用)</p>
    {{ form_obj.as_p }}  
    {{ form_obj.as_ul }}
    {{ form_obj.as_table }}
    
    <p>第二种渲染页面的方式(可扩展性较高 书写麻烦)</p>
    <p>{{ form_obj.username.label }}{{ form_obj.username }}</p>
    <p>{{ form_obj.password.label }}{{ form_obj.password }}</p>
    <p>{{ form_obj.email.label }}{{ form_obj.email }}</p>
    
    <p>第三种渲染页面的方式(推荐)</p>
    {% for foo in form_obj %}
    <p>{{ foo.label }}{{ foo }}</p>
    {% endfor %}
    
    

    **注意事项
    1.forms组件在帮你渲染页面的时候 只会渲染获取用户输入的标签 提交按钮需要你手动添加
    2.input框的label注释 不指定的情况下 默认用的类中字段的首字母大写**

    校验数据的时候可以前后端都校验 做一个双重的校验
    但是前端的校验可有可无 而后端的校验则必须要有,因为前端的校验可以通过爬虫直接避开
    前端取消浏览器校验功能
    form标签指定novalidate属性即可

    <form action="" method='post' novalidate></form>
    
    3.展示错误信息

    前端代码

    {% for foo in form_obj %}
    <p>{{ foo.label }}:{{ foo }}
        <span>{{ foo.errors.0 }}</span>
    </p>
    {% endfor %}
    

    后端代码

    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开头')])  # 密码最长八位最短五位
    

    支持正则表达式

    validators=[RegexValidator(r'[1]+$', '请输入数字'), RegexValidator(r'^159[0-9]+$', '数字必须以159开头')]

    4.钩子函数(HOOK)

    ​ forms组件暴露给用户 可以自定义的校验规则

    用法:在自定义的form类中书写方法即可
    # 局部钩子(针对某一个字段做额外的校验)   校验用户名中不能包含666 一旦包含 提示
    def clean_username(self):
        username = self.cleaned_data.get('username')
        if '666' in username:
            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
    
    5.forms组件其他字段及操作方式
    required  是否必填
    			label 		注释信息
    			error_messages  报错信息
    			
    			initial		默认值
    			
    			widget		控制标签属性和样式
    				widget=widgets.PasswordInput()
    				控制标签属性
    					 widget=widgets.PasswordInput(attrs={'class':'form-control c1 c2','username':'jason'})
    			
    其他字段了解知识点(知道有这些对象 需要用到的时候 能够知道去哪找)
    # 单选的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()
    )
    

    cookie与session

    ​ 由于http协议是无状态的 无法记录用户状态

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

    session就是保存在服务器上的键值对
    session虽然是保存在服务器上的键值对
    但是它是依赖于cookie工作的
    服务端返回给浏览器一个随机的字符串
    浏览器以键值对的形式保存
    sessionid:随机字符串

    浏览器在访问服务端的时候 就会将随机字符串携带上
    后端获取随机串与后端的记录的做比对
    随机字符串1:数据1
    随机字符串2:数据2

    如何操作Cookie
    django返回给客户端浏览器的都必须是HttpResponse对象
    		return HttpResponse()
    		return render()
    		return redirect()
    		
    		
    		
    		obj1 = HttpResponse()
    		return obj1
    		obj2 = render()
    		return obj2
    		obj3 = redirect()
    		return obj3
    		
    		
    		
    		设置cookie利用的就是HttpResponse对象
    			obj1.set_cookie('k1','v1')
    		
    		获取cookie
    			request.COOKIE.get()
    		
    		删除cookie
    			obj1.delete_cookie("k1")
    		
    		设置超时时间
    			max_age=None, 超时时间
    			expires=None, 超时时间(IE requires expires, so set it if hasn't been already.)
    

    session

    设置session
    request.session['name'] = 'jason'

    ​ 上面这句话会执行下面三件事

    ​ 1.先生成一个随机字符串

    ​ 2.然后将随机字符串当做k,和你要保存的数据, 保存在django_session表中,这是中间件帮你完成的

    ​ 3.然后将随机字符串发送给前端

    获取session

    ​ request.session.get('name')

    ​ 上面这句话会执行下面三件事

    ​ 1.前端发送来的随机字符串,Django内部会自动帮你处理

    ​ 2.会将随机字符串去django_session中进行比对

    ​ 3.一旦比对成功,会将对应的数据解析并放入request.session中

    Django默认session超时时间14天

    删除当前会话的所有Session数据

    request.session.delete()  # 删除的是前端的sessionid,就是把前端的cookie删除  delete()内可以传保存数据的k,也可以不传值
    

    删除当前的会话数据并删除会话的Cookie。

    request.session.flush()  # 将前端的cookie删除,并将后端的session数据删除
    

    这一般用于退出登录

    注意:

    ​ 一个浏览器只会保存一条session数据

    设置会话Session和Cookie的超时时间

    request.session.set_expiry(value)
    # 如果value是个整数,session会在些秒数后失效。
    # 如果value是个datatime或timedelta,session就会在这个时间后失效。
    # 如果value是0,用户关闭浏览器session就会失效。
    # 如果value是None,session会依赖全局session失效策略。
    

    总结:你在后期可以将一些数据保存到session表中,保存的数据 可以在后端任意位置获取到


    1. 0-9 ↩︎

  • 相关阅读:
    Asp.Net Web API 2第八课——Web API 2中的属性路由
    Asp.Net Web API 2第七课——Web API异常处理
    Asp.Net Web API 2第六课——Web API路由和动作选择
    Asp.Net Web API 2第五课——Web API路由
    开始学习python
    BMI 小程序 购物车
    深浅copy 文件操作
    字典 dict 集合set
    基本数据类型 (str,int,bool,tuple,)
    python 运算符
  • 原文地址:https://www.cnblogs.com/asdaa/p/11690774.html
Copyright © 2011-2022 走看看