day-63Django

ORM一对一

    列子:
            
            用户表(母表):
                id    name   age   
                1     zekai   18
            
        
            
            薪水表(子表):
                id    money   us_id
                 1      2000     1          #1这个id只能出现一次
        
        class UserInfo(models.Model):
            name = models.CharField(max_length=32)
            age = models.CharField(max_length=32)
            
        
        class Salary(models.Model):
            money = models.CharField(max_length=32)
            us = models.OneToOneField("UserInfo")
        
        
        一对一:
            #增加:
            # models.UserInfo.objects.create(name='zekai', age=18)
            
            # 查询:
            # 正向查询(子表查母表):
            # 1.11.22版本 :res.us.name
            # 1.11.10版本 : res.母表表名小写.name
            res = models.Salary.objects.filter(money="3000").first()
            print(res.us.name)


            # 反向查询(母表查子表)
            # obj.子表小写.子表列名 
            res = models.UserInfo.objects.filter(name='zekai').first()
            print(res.salary.money)

Django列类型与参数

            mysql                                      django
                            
                        tinyint                                         无
                        smallint(unsigned)        SmallIntegerField (PositiveSmallIntegerField)           括号里面表示无负号
                数字    int (unsigned))             IntegerField   (PositiveIntegerField)
                        mediumint                                    无
                        bigint(unsigned)                    BigIntegerField                                           没有无负号单词
                        
                        float                                  FloatField
                        decimal(5,2) : 200.23                  DecimalField
                        小数点后面2位,总共5位
                        
                        char                                        无
                字符串    varchar                                 CharFiled
                        text                                    TextField
                        
                        
                时间     datetime (2019-7-17 12:23:34)        DateTimeField        
                         date      (2019-7-17)                  DateField
                         
                     
                - 参数:
                    max_length=32        字符串最大长度
                    null=True  :        可以设置为null
                    db_index=True :     设置索引
                    default :           设置默认值
                    unique :            设置唯一索引
                    db_column:           在表中重新取一个名字
                    unique_together:     联合唯一索引
                    index_together :    普通联合索引
                    
                    案例:
                        class xxx():
                            表模型类
                            
                            class Meta:
                                unique_together = (
                                    ('money', 'us_id'),
                                    ....
                                )
                                index_together = (
                                    ('money', 'us_id')
                                    ....
                                )
            

Django-admin列类型与参数

djagno-admin:
    django自带的管理后台系统
    
用户名、密码命令生成:
    python3 manage.py  createsuperuser
    
如何管理自己生成的表:  
    每个app下admin文件中导入模型:
        from app01 import models
        admin.site.register(models.UserInfo)
        
    下面都是在django-admin中生效
    
        django-admin中的列类型:
            EmailField(CharField):
                - 字符串类型,Django Admin以及ModelForm中提供验证机制
            IPAddressField(Field)
                - 字符串类型,Django Admin以及ModelForm中提供验证 IPV4 机制
            GenericIPAddressField(Field)
                - 字符串类型,Django Admin以及ModelForm中提供验证 Ipv4和Ipv6
                - 参数:
                    protocol,用于指定Ipv4或Ipv6, 'both',"ipv4","ipv6"
                    unpack_ipv4, 如果指定为True,则输入::ffff:192.0.2.1时候,可解析为192.0.2.1,开启刺功能,需要protocol="both"
            URLField(CharField)
                - 字符串类型,Django Admin以及ModelForm中提供验证 URL
            SlugField(CharField)
                - 字符串类型,Django Admin以及ModelForm中提供验证支持 字母、数字、下划线、连接符(减号)
            CommaSeparatedIntegerField(CharField)
                - 字符串类型,格式必须为逗号分割的数字
            UUIDField(Field)
                - 字符串类型,Django Admin以及ModelForm中提供对UUID格式的验证
            FileField(Field)
    
        djagno-admin中的参数 :
            verbose_name        Admin中显示的字段名称            
            blank               Admin中是否允许用户输入为空
            editable            Admin中是否可以隐藏
            help_text           Admin中该字段的提示信息
            choices             Admin中显示选择框的内容,用不变动的数据放在内存中从而避免跨表操作
            
            choices = (
                (1, ''),
                (2, '')
                                #1是mysql表现形式   男女是djagno-admin表现形式
            )
            gender = models.IntegerField(choices=chocies)
            
        
            
             from django.core.validators import RegexValidator
             
             test3 = models.CharField(
                 max_length=32,
                 error_messages={                       #优先级,先c1再mes
                     'c1': '优先错信息1',
                     'c2': '优先错信息2',
                    'c3': '优先错信息3',
                 },
                 validators=[RegexValidator(regex='root_d+', message='错误了', code='c1')]
            )

Django内置分页

def index(request):
    from django,core,paginator import Paginator,EmptyPage(用户点击页数超出页面总页面数,用万能异常能捕获到·)

 1. 接收页数 
 
    try:
     cur_page = request.GET.get('cur_page')             #接收的是用户点击的第几页
        cur_page = int(cur_page)               #强行报错
    except Exception as e:
        cur_page = 1

    user_list = models.UserInfo.objects.all()
  

 2.拿到页数数据 
 
    paginator = Paginator(user_list, 10)                #括号里边是(列表套对象,每页多少条数据)
    
    #paginator这个对象有下面这些方法:
    
    # per_page:                     每页显示多少条数据
    # count:                        传过来数据总个数(多少条)
    # num_pages:                    一共能显示多少页
    # page_range:                   一共能显示多少页索引范围,如: 索引范围是1到10 ,就是翻页能从1点到10
    # page:                         后面点page能获得page的方法,如下
    
    
 3.发送到html
    users = paginator.page(cur_page)                    #参数是用户点击的第几页,而users就是用户点击的第几页的所有数据
    
  
    #users的方法:
    
    # has_next                      是否有下一页
    # next_page_number              获取下一页页码
    # has_previous                  是否有上一页
    # previous_page_number          获取上一页页码
    # object_list                   用户点击的第几页的数据列表
    # number                        当前页码
    # paginator                     又可以点paginator对象,获得paginator的方法
    
    
    return render(request, "index.html", {"user_list":users})
    
 4.在html使用方法 
        #users传到html后,就可以在html点上面的所有方法

html代码:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Title</title>
</head>
<body>
    <ul>
        {% for user in user_list.object_list %}
            <li>{{ user.name }}</li>
        {% endfor %}
    </ul>

    {% if user_list.has_previous %}
        <a href="/index/?cur_page={{ user_list.previous_page_number }}">上一页</a>
    {% endif %}

    {% for num in user_list.paginator.page_range %}
        
            <a  href="/index/?cur_page={{ num }}">{{ num }}</a>
                       
    {% endfor %}

    {% if user_list.has_next %}
        <a href="/index/?cur_page={{ user_list.next_page_number }}">下一页</a>
    {% endif %}



</body>
</html>

手写分页

# 自定制的分页类
class PageInfo():
    def __init__(self, cur_page, total, per_page=10, show_page=11):
                        
                        
        cur_page        用户点击的第多少页         
                       
        total           表有多少条数据     
        
        per_page        每页多少条数据
        
        show_page       显示当前页数一共为11页
        
        
        try:
            self.cur_page = int(cur_page)
        except  Exception as e:                                 #如果传入不是数字强行报错
            self.cur_page = 1

        self.per_page = per_page
        self.show_page = show_page
        

        a, b = divmod(total, per_page)                          #前面整除的数字,后面是余数的数字(301,10)=>(30,1)
        if b:
            self.total_page = a + 1                             #定义一个self.total_page(总页数)
        else:
            self.total_page = a
            

    def get_start(self):                                        #切片的开始位置
        return (self.cur_page - 1) * self.per_page

    def get_stop(self):                                         #切片的接收位置
        return  self.cur_page * self.per_page
        
        
        

    def page(self):                                             #拼接自己写好的html标签

        half = int((self.show_page ) / 2)                       #为了区分点击两边的区域


      
        if self.total_page < self.show_page:                    #要显示的页数小于要展示的页数show_page(数据太少)
            begin = 1
            stop = self.total_page + 1
            
            
        else:
            # 下面代码可以自定义,比如:begin = self.cur_page  - half
            # 显示效果是左右越点越少
            
            
            if self.cur_page - 1 < half:                        #靠最左边点击会出现负数的情况
                begin = 1
                stop = self.show_page + 1
                
            elif self.cur_page + half > self.total_page:        #靠最右边点击会出现超出页数的情况
                begin = self.total_page - self.show_page + 1
                stop = self.total_page + 1
                
            else:                                               #正常显示数据
                begin = self.cur_page - half
                stop = self.cur_page  + half + 1

        sli = []        
        if self.cur_page == 1:                                   #如果上一页一直点到第一页,在点会出现负数并报错,所以用#让它处在第一页
            s =  "<li class='disabled'><a href='#'>上一页</a></li>"
        else:
            s =  "<li><a   href='/custom/?cur_page=%s'>上一页</a></li>" %(self.cur_page - 1)  #没有上述情况,就进行跳转

        sli.append(s)

        for num in range(begin, stop):                                                         #为了显示高亮
            if num == self.cur_page:
                s = "<li class='active'><a   href='/custom/?cur_page=%s'>%s</a></li>" %(num, num)
            else:
                s = "<li><a   href='/custom/?cur_page=%s'>%s</a></li>" %(num, num)
            sli.append(s)

        if self.cur_page == self.total_page:                                                   #作用同上一页一样
            s = "<li  class='disabled'><a  href='#'>下一页</a></li>"
        else:
            s = "<li><a  href='/custom/?cur_page=%s'>下一页</a></li>" % (self.cur_page + 1)
        sli.append(s)

        page_str = " ".join(sli)                                                               #在列表中,把逗号换成空,返回一个字符串

        return page_str

# 自定制的分页函数

    def custom(request):

      cur_page = request.GET.get('cur_page')                             #用户点击的第几页(一开始需要自己来传)

      total = models.UserInfo.objects.count() 
      pageinfo = PageInfo(cur_page, total)
      start = pageinfo.get_start()
      stop = pageinfo.get_stop()
      user_list = models.UserInfo.objects.all()[start:stop]

      return render(request, "custom.html",{"user_list":user_list, "pageinfo":pageinfo})    #将对象传入html,在html中可以使用点方法

#推导理论

 cur_page start stop
 1     0   10
 2     10   20
 3     20   30
 n  (n-1)*per_page  n * per_page

html代码(需要bs引入):

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Title</title>
    <!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css"
 integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
</head>
<body>
    <ul>
        {% for user in user_list %}

            <li>{{ user.name }}</li>
        {% endfor %}
    </ul>



    <nav aria-label="Page navigation">
      <ul class="pagination">
        {{ pageinfo.page | safe }}
      </ul>
</nav>
</body>
</html>

CSRF:

  跨站请求伪造

  原理:在对方使用的浏览器上拿到对方的cookie,使用这个cookie进行对对方访问过的网站,进行访问和操作
  造成原因:用户使用同一个浏览器打开两个网站,第一个网站状态还没有退出,
         而第二个网站不受信用,如果在第二个网站进行操作,就有可能受到攻击
  解决方案:浏览器在请求服务器的时候,服务器除了返回数据和cookie,还在返回了token,
         而tokin放在发的html中的form表单,下次再次访问,会和服务器存的token进行比对,不一样拒绝访问
  不同之处:tokin一般获取不到,而cookie可以,并且tokin要先于cookie传入浏览器

 中间件开启的时候,表示开启全局的csrf验证(token验证):
            
            HTML处理方法
                    1. 在form表单中生成cookie
                    <form>
                        {% csrf_token %}        在form表单中生成cookie
                        <input type='text'>
                    </form>
            
            
            
        
                
            FBV处理方法    
                    1..下面函数关闭csrf验证
                    from django.views.decorators.csrf import csrf_exempt                    
                    @csrf_exempt
                    def csrf1(request):
                        if request.method == 'GET':
                            return render(request, 'csrf1.html')
                        else:
                            return HttpResponse('ok')
                
            
            
 当中间件关闭的时候:
                    1.下面函数开启csrf验证
                    from django.views.decorators.csrf import csrf_protect                    
                    @csrf_protect
                    def csrf1(request):
                        if request.method == 'GET':
                            return render(request, 'csrf1.html')
                        else:
                            return HttpResponse('ok')
            
            
        
            CBV处理方法:
                    from django.utils.decorators import method_decorator
                    @method_decorator(csrf_protect, name='get')
                                    #里面第一个是上述开启或关闭方法,第二个是对哪个请求有作用,也可以不写
                    class User(View):
                        def get(self, request):
                            pass
                        def post(self, request):
                            pass
                            
          
            ajax处理方法:
                csrftoken = $('input[name="csrfmiddlewaretoken"]').val()    #属性选择器
                $.ajax({
                    type:"POST",
                    url : '/xxxx/',
                    data: {"name":'xxxx'},
                    headers : {'X-CSRFToken': token},                       #自己获取表单的token,放进去发送                                  
                    success: function(){
                        console.log(data)
                    }
                })
原文地址:https://www.cnblogs.com/klw1/p/11202306.html