zoukankan      html  css  js  c++  java
  • 7,复习,多对多表的三种创建,form组件,cookie,session

    昨日内容回顾
     choices字段
      只要是能够罗列出来的有限个选项的都可以使用choices字段来做
       1.学历,工作经历,性别,工作状态,客户来源,婚嫁
       gender_choices = ((1,'male'),(2,'female'),(3,'others'))
       gender = models.IntegerField(choices=gender_choices)
       # 当gender存的是gender_choices中罗列的数字 那么就会有对应关系
       # 但是如果存的数字不存在 那么也不会报错 正常存储  只不过没有了对应关系而已
       2.
        user_obj.gender  # 结果是数字
        user_obj.get_gender_display()  # 拿到数字所对应的注释
        
     MTV与MVC模型
      django自称为是MTV但是你要知道MTV其实本质也是MVC
      
     Ajax
      异步提交 局部刷新
      基本语法结构
       $.ajax({
        url:'',  # 默认不写就是当前路径(不写,后缀,全称)
        type:'post',  # 请求方式
        data:{'name':'jason'}  # 数据  数据默认的格式是urlencoded(name=jason&pwd=123)
        success:function(data){  # data就是后返回的异步提交的结果 通常都是一个字典
         if (data.code == 1000){
          # 状态码是1000的情况需要走的逻辑
         }elif(data.code == 2000){
          # 状态码是2000的情况需要走的逻辑
         }else{
          # 其他情况 需要的操作
         } 
        }
      
       })
       通常情况下 后端针对ajax交互 都是采取字典的形式
       
      contentType
       前后端传输数据的编码方式
        1.urlencoded    >>>    name=jason&pwd=123&hobby=read
        2.formdata     >>>    传文件也支持传普通键值(name=jason&pwd=123&hobby=read)
        3.application/json  >>>     json格式数据(form表单是无法发送json格式数据的)
       
       form,ajax表单默认的是urlencoded
       
       django后端针对不同的编码格式是如何处理的?
        只要是符合urlencoded编码格式  都会被后端自动获取并解析放到request.POST中
        如果是符合formdata那么文件会自动被解析放到request.FILES中
        如果是json格式 后端默认不解析 以二进制的形式就放在request.body你可以自己手动处理即可
       
       ajax发送json格式数据
        """前后端传输数据 一定要确保数据与编码方式的一致性"""
         $.ajax({
          url:'',  # 默认不写就是当前路径(不写,后缀,全称)
          type:'post',  # 请求方式
          data:JSON.stringify({'name':'jason'}),  # 数据  数据默认的格式是urlencoded(name=jason&pwd=123)
          contentType:'application/json',
          success:function(data){  # data就是后返回的异步提交的结果 通常都是一个字典
          if (data.code == 1000){
           # 状态码是1000的情况需要走的逻辑
          }elif(data.code == 2000){
           # 状态码是2000的情况需要走的逻辑
          }else{
           # 其他情况 需要的操作
          } 
         }
       
        })
       
       ajax发送文件
        1.利用内置对象FormData
         既可以传文件也可以传普通的键值对
        2.获取input标签存储的文件对象
         先用jQuery找到该input标签,然后转成原生的js对象
         然后固定语法.files[0]
         $('input')[0].files[0]
        3.发送ajax请求
         有两个关键性的参数需要你指定
          processData:false
          contentType:false
        django后端就会普通的键值解析到request.POST中文件解析到request.FILES
     
     sweetalert
      注意推导思路
      删除弹框
      作业:图书管理的系统的删除书籍功能
     
     序列化组件
      from django.core import serializers
     
     自定义分页器
      1.quertset支持切片取值
      
      需要你掌握的就是推导思路
      后端
      book_list = models.Book.objects.all()
      page_obj = Paganation(current_page= request.GET.get('page',1),all_count=book_list.count())
      page_query = book_list[page_obj.start:page_obj.end]
      # 将page_query,page_obj传递到前端即可
       
       
      前端
       确保你的html页面引入了bootstrap文件
       
       # for循环page_query展示数据
       # page_obj.page_html|safe生成分页器页码样式
       
      
      
    今日内容
     多对多三种创建方式
      1.全自动(推荐使用*)
       优势:不需要你手动创建第三张表
       不足:由于第三张表不是你手动创建的,也就意味着第三张表字段是固定的无法做扩展
       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.半自动(推荐使用******)
       优势:结合了全自动和纯手动的两个优点
       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)
     
     forms组件
      自己手动实现一个注册功能
      当用户的用户名包含西游记   提示不符合社会主义核心价值观
      当用户的密码短于3位   提示密码太短了 不符合要求
      
      
      1.前端页面搭建      >>>  渲染页面
      2.将数据传输到后端做校验  >>>  校验数据
      3.展示错误信息     >>>  展示信息
      
      案列: 前端页面搭建
        <form action="" method="post">
         <p>username:<input type="text" name="username">
          <span style="color: red">{{ errors.username }}</span>
         </p>
         <p>password:<input type="password" name="password">
          <span style="color: red">{{ errors.password }}</span>
         </p>
         <input type="submit" class="btn btn-success">
        </form>
        将数据传输到后端做校验:
        def login(request):
         errors = {'username':'','password':''}
         if request.method == 'POST':
          username =request.POST.get('username')
          password = request.POST.get('password')
          if  '西游记' in username:
           errors['username'] = '不符合社会主义价值观'   #展示错误信息
          if len(password)< 3:
           errors['password'] = '太短了,不符合要求'         #展示错误信息
         return render(request,'login.html',locals())
      
      
      
      forms组件能够直接帮你完成上面的三步操作   注意优点是直接完成上面三步操作
       1.渲染前端页面
       2.校验数据是否合法
       3.展示错误信息
      
      1.forms组件基本用法(校验功能)
       1.写一个基础了forms.Form的类(在视图层)
        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.基本使用 #在测试文件或者pycharm终端中
        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组件在帮你渲染页面的时候 只会渲染获取用户输入的标签  提交按钮需要你手动添加
         即需要手动加input框submit
        
        2.input框的label注释  不指定的情况下 默认用的类中字段的首字母大写
        
      校验数据的时候可以前后端都校验 做一个双重的校验
      但是前端的校验可有可无 而后端的校验则必须要有,因为前端的校验可以通过爬虫直接避开
       前端取消浏览器校验功能
        form标签指定novalidate属性即可
         <form action="" method='post' novalidate></form>
        
        获取中文注释:只需在字段后面加个label='xxx',因为在前端获取时就是对象点属性{{ foo.label }}
         class LoginForm(forms.Form): 例如  label='用户名'
          username = forms.CharField(max_length=8,min_length=3,label='用户名')  # 用户名最长八位最短三位
          password = forms.CharField(max_length=8,min_length=5,label='密码')  # 密码最长八位最短五位
          email = forms.EmailField(label='邮箱')  # email必须是邮箱格式
        
      
      3.展示错误信息
       {% for foo in form_obj %}
        <p>{{ foo.label }}:{{ foo }}
        <span>{{ foo.errors.0 }}</span>  #点零只拿内部文本信息,不会再渲染标签,你写什么标签就是什么标签,不会被打乱
        </p>        #foo.errors会渲染标签,把标签内部结构打乱
       {% 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开头')])  # 密码最长八位最短五位
         
          required=False  就是即这个字段可以不填,前端不用传值,但是后端不能为空还在校验
          不仅支持正则校验 此外还支持函数
          
         暴露了几个接口:即钩子函数
      4.钩子函数(HOOK)
       forms组件暴露给用户 可以自定义的校验规则
       
       全局钩子 针对多个字段做额外的校验
       
       
       局部钩子   针对某一个字段做额外的校验
       
       
       用法:在自定义的form类中书写方法即可 即你自己定义的LoginForm类
       # 局部钩子(针对某一个字段做额外的校验)   校验用户名中不能包含666 一旦包含 提示
       def clean_username(self):
        username = self.cleaned_data.get('username')
        if '666' in username:
         self.add_error('username','光喊666是不行的 你得自己上')# 第一个参数是你想把这个报错信息给那个input框,第二个报错是报错信息
        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组件其他字段及操作方式  例如class属性
       required  是否必填(为空)
       label   注释信息          label='用户名'
       error_messages  报错信息
       
       initial  默认值
       
       案例:
       password = forms.CharField(max_length=8,min_length=5,label='密码',initial='tankdsb',
        error_messages={
                                       'max_length':'密码最大八位',
                                       'min_length':'密码最小五位',
                                       'required':'密码不能为空'
                                   },required=False,widget=widgets.PasswordInput())
       
       widget  控制标签属性和样式 
        widget=widgets.PasswordInput()  密码变为密文
        控制标签属性
         给标签添加属性,此时案例为增加class属性 增加多个属性,空格隔开,增加class属性,c1属性,c2属性,例如'class':'form-control c1 c2'
          自定义属性,例如'username':'jason'   具体如下:
          widget=widgets.PasswordInput(attrs={'class':'form-control c1 c2','username':'jason'})
       
       其他字段了解知识点(知道有这些对象 需要用到的时候 能够知道去哪找)
        forms.widgets   后面跟选择的那个框,是select框,还是input框
        # 单选的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()
        )
        
       ChoiceField都是当选字段
      
      forms组件源码分析
       form_obj.is_valid()
      
      
     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.django 内部自动生成一个随机字符串
        2.将随机字符串和你要保存的数据 写入django_session表中(现在内存中生成一个缓存记录 等到经过中间件的时候才会执行)
        3.将产生的随机字符串发送给浏览器写入cookie
         sessionid:随机字符串
       """
      获取session
       request.session.get('name')
       """
       上面这一句话发生了三件事
        1.django内部会自动从请求信息中获取到随机字符串
        2.拿着随机字符串去django_session表中比对
        3.一旦对应上了就将对应的数据解析出来放到request.session中
       
       """
      
      django session默认的超时时间是14天
      
      
      django_session表中的一条记录针对一个浏览器
      
      
      # 删除当前会话的所有Session数据
      request.session.delete()  # 删除的是浏览器的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失效策略。
     
     总结:你在后期可以将一些数据保存到session表中,保存的数据 可以在后端任意位置获取到
      
      
  • 相关阅读:
    龙井和碧螺春的功效与作用
    064 01 Android 零基础入门 01 Java基础语法 08 Java方法 02 无参带返回值方法
    063 01 Android 零基础入门 01 Java基础语法 08 Java方法 01 无参无返回值方法
    062 01 Android 零基础入门 01 Java基础语法 07 Java二维数组 01 二维数组应用
    061 01 Android 零基础入门 01 Java基础语法 06 Java一维数组 08 一维数组总结
    060 01 Android 零基础入门 01 Java基础语法 06 Java一维数组 07 冒泡排序
    059 01 Android 零基础入门 01 Java基础语法 06 Java一维数组 06 增强型for循环
    058 01 Android 零基础入门 01 Java基础语法 06 Java一维数组 05 案例:求数组元素的最大值
    057 01 Android 零基础入门 01 Java基础语法 06 Java一维数组 04 案例:求整型数组的数组元素的元素值累加和
    056 01 Android 零基础入门 01 Java基础语法 06 Java一维数组 03 一维数组的应用
  • 原文地址:https://www.cnblogs.com/Fzhiyuan/p/11582093.html
Copyright © 2011-2022 走看看