zoukankan      html  css  js  c++  java
  • CSIC_716_2020110【Django入门---多对多表关系的三种创建方式、Ajax、自定义分页器、删除的二次弹窗确认】

    多对多表关系的建立方式(以图书表和作者表为例)

    多对多表关系的创建有三种方式:自动创建、手动创建、半自动创建

    前文中已经介绍了多对多的全自动创建方式,但是创建的第三张表中只有两个外键字段,因为是该表是django自动生成的,故没办法在第三张表中增加其余字段

    本文介绍剩余的两种:

    纯手动创建以及半自动创建

    纯手动创建

    特点:多对多的第三张关系表是自己手动创建的,相较于全自动创建而言,在关系表中除外键外还可以添加任意字段。

    不足:在跨表查询的时候比较麻烦,不可以使用django orm提供的便利方法

    class Book(models.Model):
        title = models.CharField(max_length= 32 )
        price = models.DecimalField(max_digits=8, max_places=2)
    
    
    class Author(models.Model):
        name = models.CharField(max_length = 32)
        age = models.IntegerField()
     
    
    class Book2Author(models.Model):
        book = models.ForeignKey(to = 'Book')
        author = models.ForeignKey(to = 'Author')
        remark = models.CharField(max_length = 32)
    

      

    半自动创建

    外键建在book表中  注意外键括号内参数的区别

    class Book(models.Model):
        title = models.CharField(max_length= 32 )
        price = models.DecimalField(max_digits=8, max_places=2)
        authors = models.ManyToMany(to='Author', through=‘Book2Author’,through_fields=('book','author'))
    
    
    class Author(models.Model):
        name = models.CharField(max_length = 32)
        age = models.IntegerField()
     
    
    class Book2Author(models.Model):
        book = models.ForeignKey(to='Book')
        author = models.ForeignKey(to ='Author')
        remark = models.CharField(max_length = 32)
    

      外键建在author中

    class Book(models.Model):
        title = models.CharField(max_length= 32 )
        price = models.DecimalField(max_digits=8, max_places=2)
        
    
    class Author(models.Model):
        name = models.CharField(max_length = 32)
        age = models.IntegerField()
        books= models.ManyToMany(to='Book', through=‘Book2Author’,through_fields=('author','book'))
     
    
    class Book2Author(models.Model):
        book = models.ForeignKey(to='Book')
        author = models.ForeignKey(to ='Author')
        remark = models.CharField(max_length = 32)
    

      优点:扩展性强,可以在关系表总增加任意字段,并且还可以使用orm提供的跨表查询的方法,推荐

    缺点: orm提供的多对多外键的增删改查没办法使用了即无法使用 add、set、remove、clear四个方法无法使用。

    Ajax

    ajax的特点:异步提交,局部刷新。Ajax是通过js语言写的一个功能模块,本文学习的是通过jQuery封装好的ajax模块

    目前本人已知的与后端交互的方式有如下四种:

    1、浏览器窗口中直接写网址:请求方式GET;

    2、<a>标签中的 href后面填写url :请求方式GET;

    3、form表单    :    GET和POST请求都可以;

    4、Ajax:   GET和POST请求都可以;

    Ajax的基本语法结构:

    四个步骤:向哪个地址提交、以什么请求方式、提交什么内容、返回的结果如何处理

    $.ajax({
        urls:' ',   #可以填具体的url,也可以填地址的后缀,也可以不填默认提交到当前
        type:' ',     # type的类型有get和post
        data:{ },     # 必须要保证是个字典的样式传
        success:function(data):{     #data为后端处理后传到前端的值
                代码块
                代码块
            }
    })
    

      

    form表单默认的是以urlencoded的编码格式传输数据,后端接收到数据后会先存入request.body,然后再将键值对数据自动存到request.POST中;当表单中有普通键值对和文件时,就需要修改enctype属性,以formdata编码格式传输数据,后端接收到数据后会先存入request.body,然后再将普通键值对存到request.POST中,将文件数据存入request.FILES中。

    Ajax也是默认以urlencoded方式传输数据,Ajax中有一个contentType属性可以指定编码方式,除了urlencoded外还支持application/json,但是如果明确了contentType是application/json时,data后面的数据就一定要是json类型的数据,可以借助Javascript中自带的序列化方法JSON.stringify,后端接收到的数据以二进制形式存放在request.body中,后端可以通过json.loads(request.body)取值,loads可以直接将符合json格式的二进制数据反序列化,举例如下:

    $.ajax({
        urls:' ' ,   
        type:' ' ,
    
        contentType:'application/json' ,
        data:JSON.stringify({ }) ,  
    
        success:function(data):{     
                代码块
            }
    }) 
    

      

    需要注意的是,如果前端以json形式发到后端,后端收到值后,会存放到request.body中,取j值直接从request.body中取,取出来的是一组二进制的json数据。

    这时候按照套路应该先解码再反序列化。但是在后端,json.loads(二进制json)会直接先解码再反序列化

    )

     Ajax发送文件数据

    这里需要使用JavaScript的内置对象FormData,它既可以存键值对也能存文件。

    $(#d1).on('click', function(){   //给id为d1的按钮绑定click方法
      var myFormData = new FormData();
      myFormData.append( 'key', 'value' ) ; //普通键值写入的方法
      myFormData.append( 'key', '$(#d1)[0]files[0]');
    //数据组织完了,下面开始Ajax操作
      $.ajax({
        url:' ',
        type:'post' ,
        data:myFormData,
    //发送FormData对象需要指定下面两个关键的参数
        processData:false,  //让浏览器不要动数据
        contentType: false,  //不使用编码格式,因为FormData自带django能识别的编码格式
        success:function(data){
            代码块
          }
      })
    })
    

      

     django内置的序列化功能     后期会介绍drf

    在线JSON校验格式化工具    BeJSON

    序列化模块  serializers

    from django.core import   serializers

    res = serializers.serialize('json' , queryset)  // 第一个参数是明确序列化成json格式,第二个参数是提供一个queryset对象

     批量向数据库中插入数据的方式

     使用 models.Book.objects.bulk_create(对象列表)

    def bulk_create(request):
        list_obj = []
        #通过for循环生成对象,再将对象append进list_obj中
        for i in range(1000):
             list_obj.append(models.Book(title = '第%s本书'% i))
         models.Book.objects.bulk_create(list_obj)
         book_queryset = models.Book.objects.all()
         return ....
    

      

     自定义分页器

     略

      1 class Pagination(object):
      2     def __init__(self, current_page, all_count, per_page_num=10, pager_count=11):
      3         """
      4         封装分页相关数据
      5         :param current_page: 当前页
      6         :param all_count:    数据库中的数据总条数
      7         :param per_page_num: 每页显示的数据条数
      8         :param pager_count:  最多显示的页码个数
      9 
     10         用法:
     11         queryset = model.objects.all()
     12         page_obj = Pagination(current_page,all_count)
     13         page_data = queryset[page_obj.start:page_obj.end]
     14         获取数据用page_data而不再使用原始的queryset
     15         获取前端分页样式用page_obj.page_html
     16         """
     17         try:
     18             current_page = int(current_page)
     19         except Exception as e:
     20             current_page = 1
     21 
     22         if current_page < 1:
     23             current_page = 1
     24 
     25         self.current_page = current_page
     26 
     27         self.all_count = all_count
     28         self.per_page_num = per_page_num
     29 
     30         # 总页码
     31         all_pager, tmp = divmod(all_count, per_page_num)
     32         if tmp:
     33             all_pager += 1
     34         self.all_pager = all_pager
     35 
     36         self.pager_count = pager_count
     37         self.pager_count_half = int((pager_count - 1) / 2)
     38 
     39     @property
     40     def start(self):
     41         return (self.current_page - 1) * self.per_page_num
     42 
     43     @property
     44     def end(self):
     45         return self.current_page * self.per_page_num
     46 
     47     def page_html(self):
     48         # 如果总页码 < 11个:
     49         if self.all_pager <= self.pager_count:
     50             pager_start = 1
     51             pager_end = self.all_pager + 1
     52         # 总页码  > 11
     53         else:
     54             # 当前页如果<=页面上最多显示11/2个页码
     55             if self.current_page <= self.pager_count_half:
     56                 pager_start = 1
     57                 pager_end = self.pager_count + 1
     58 
     59             # 当前页大于5
     60             else:
     61                 # 页码翻到最后
     62                 if (self.current_page + self.pager_count_half) > self.all_pager:
     63                     pager_end = self.all_pager + 1
     64                     pager_start = self.all_pager - self.pager_count + 1
     65                 else:
     66                     pager_start = self.current_page - self.pager_count_half
     67                     pager_end = self.current_page + self.pager_count_half + 1
     68 
     69         page_html_list = []
     70         # 添加前面的nav和ul标签
     71         page_html_list.append('''
     72                     <nav aria-label='Page navigation>'
     73                     <ul class='pagination'>
     74                 ''')
     75         first_page = '<li><a href="?page=%s">首页</a></li>' % (1)
     76         page_html_list.append(first_page)
     77 
     78         if self.current_page <= 1:
     79             prev_page = '<li class="disabled"><a href="#">上一页</a></li>'
     80         else:
     81             prev_page = '<li><a href="?page=%s">上一页</a></li>' % (self.current_page - 1,)
     82 
     83         page_html_list.append(prev_page)
     84 
     85         for i in range(pager_start, pager_end):
     86             if i == self.current_page:
     87                 temp = '<li class="active"><a href="?page=%s">%s</a></li>' % (i, i,)
     88             else:
     89                 temp = '<li><a href="?page=%s">%s</a></li>' % (i, i,)
     90             page_html_list.append(temp)
     91 
     92         if self.current_page >= self.all_pager:
     93             next_page = '<li class="disabled"><a href="#">下一页</a></li>'
     94         else:
     95             next_page = '<li><a href="?page=%s">下一页</a></li>' % (self.current_page + 1,)
     96         page_html_list.append(next_page)
     97 
     98         last_page = '<li><a href="?page=%s">尾页</a></li>' % (self.all_pager,)
     99         page_html_list.append(last_page)
    100         # 尾部添加标签
    101         page_html_list.append('''
    102                                            </nav>
    103                                            </ul>
    104                                        ''')
    105         return ''.join(page_html_list)
    自定义分页器引用文件
     current_page = request.GET.get('page', 1)
        all_count = book_queryset.count()
        # 1 现生成一个自定义分页器类对象
        page_obj = Pagination(current_page=current_page,all_count=all_count,pager_count=9)
        # 2 针对真实的queryset数据进行切片操作
        page_queryset = book_queryset[page_obj.start:page_obj.end]
    自定义分页器后端
    {% for book_obj in page_queryset %}
        <p>{{ book_obj.title }}</p>
    {% endfor %}
    {{ page_obj.page_html|safe }}
    自定义分页器前端

    Ajax结合Sweetalert实现删除二次确认

     代码

     SweetAlert for Bootstrap

  • 相关阅读:
    CSS定位属性
    CSS属性
    CSS基础
    HTML
    JDBC
    语言元素
    初识Python
    redis配置文件
    zabbix
    jumpserver
  • 原文地址:https://www.cnblogs.com/csic716/p/12177006.html
Copyright © 2011-2022 走看看