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 ↩︎

  • 相关阅读:
    Source Insight技巧收集
    宝贝,祝你生日快乐!
    【转载】C++中的extern C
    Meego
    source insight增加新类型方法
    点操作符和箭头操作符的异同
    【转载】mtk编译命令
    margin和padding的用法与区别以及bug处理方式
    js数组
    随机验证码,颜色同时刷新
  • 原文地址:https://www.cnblogs.com/asdaa/p/11690774.html
Copyright © 2011-2022 走看看