首页 > 其他分享 >Ajax补充说明 Django内置序列化组件 ORM批量操作数据 分页器 form组件

Ajax补充说明 Django内置序列化组件 ORM批量操作数据 分页器 form组件

时间:2022-12-20 20:23:26浏览次数:56  
标签:models self Django current book 组件 序列化 pager page

目录

Ajax补充说明

主要针对回调函数args接收到后端的响应数据

1.后端request.is_ajax()

后端用于判断当前用户的请求是否由Ajax发出

image

结果:
image

还可以再细分

image

2.后端返回的三板斧都会被args接收不再影响整个浏览器页面

前端:

image

后端:

image

结果:

返回了整个前端页面 都被args形参接收了

image

3.选择使用ajax做前后端交互的时候 后端一般返回的都是字典数据

jax做前后端交互 后端返回的都是字典得形式返回Ajax

image

我们可以自定义状态码 返回到前端ajax 那么Ajax就可以通过判断code的状态码是多少 从而做出不同的效果

image

那么怎么把字典返回给前端呢? 前端默认是字符串 而字典不是字符串

有两种方式

方式一:

用json.dumps把字典序列化处理转成JSON字符串类型的数据 而HttpResponse就能返回字符串数据类型J

image

前端接收的序列化数据

image

在前端再反序列化成js的自定义对象

image

结果:

image

那么以上太麻烦了都得自己转

方式二:

我们还学过JsonResponse 默认发送字典 更加的见名知意

image

前端

image

结果:

image

直接变自定义对象 这样在前端就不用自己转了

所以当在后端要返回一个字典给前端时 使用JsonResponse更方便合理 就不再需要自己转了

那么在Ajax里面个参数dataType 自动解析反序列化后端的JSON格式的字符串

后端用json序列化发送

image

前端Ajax直接配置dataType:'json'
image

结果:

image

ajax自动反序列化后端的json格式的bytes类型数据dataType:'json'

多对多三种创建方式

1.全自动创建

class Book(models.Model):
    title = models.CharField(max_length=32)
    authors = models.ManyToManyField(to='Author')
class Author(models.Model):
    name = models.CharField(max_length=32)

优势:自动创建第三张表 并且提供了add、remove、set、clear四种操作
劣势:第三张表无法创建更多的字段 扩展性较差

2.纯手动写

class Book(models.Model):
    title = models.CharField(max_length=32)
class Author(models.Model):
    name = models.CharField(max_length=32)
class Book2Author(models.Model):
    book = models.ForeignKey(to='Book')
    author = models.ForeignKey(to='Author')
    others = models.CharField(max_length=32)
    join_time = models.DateField(auto_now_add=True)

优势:第三张表完全由自己创建 扩展性强
劣势:编写繁琐 并且不再支持add、remove、set、clear以及正反向概念

3.半自动创建

得要在第三张关系表创建字段 而且还支持自己写

但是在表里可以加外键字段

	 class Book(models.Model):
        title = models.CharField(max_length=32)
        authors = models.ManyToManyField(to='Author',
                          through='Book2Author',      									through_fields=('book','author')
                                        )
    class Author(models.Model):
        name = models.CharField(max_length=32)
    class Book2Author(models.Model):
        book = models.ForeignKey(to='Book', on_delete=models.CASCADE)
        author = models.ForeignKey(to='Author', on_delete=models.CASCADE)
        others = models.CharField(max_length=32)
        join_time = models.DateField(auto_now_add=True)

告诉ORM那个表是来维护书与作者表的多对多的关系 其中through_field中的字段顺序是不能乱(在书表为基表中创建的外键那么字段名book记得在前)

image

优势:第三张表完全由自己创建 扩展性强 正反向概念依然清晰可用
劣势:编写繁琐不再支持add、remove、set、clear

image

Django内置序列化组件(drf前身)

如果不创建新的表 将原来的注释掉

image

在基于原来的表中做修改重新执行同步迁移 会报错

image

将注册表中数据删除

image

将原来的表删除 再执行同步迁移

image

场景:没办法使用模板语法及return locals传到前端页面使用

前后端分离的项目 视图函数只需要返回JSON格式的数据即可

from app01 import models
from django.http import JsonResponse


def ab_ser_func(request):
    # 1.查询所有的书籍对象
    book_queryset = models.Book.objects.all()  # queryset [对象、对象]
    # 2.封装成大字典返回
    data_dict = {}
    for book_obj in book_queryset:
        temp_dict = {}
        temp_dict['pk'] = book_obj.pk
        temp_dict['title'] = book_obj.title
        temp_dict['price'] = book_obj.price
        temp_dict['info'] = book_obj.info
        data_dict[book_obj.pk] = temp_dict  # {1:{},2:{},3:{},4:{}}
    return JsonResponse(data_dict)

序列化组件(django自带 后续学更厉害的drf)
# 导入内置序列化模块
from django.core import serializers
# 调用该模块下的方法,第一个参数是你想以什么样的方式序列化你的数据
res = serializers.serialize('json', book_queryset)
return HttpResponse(res)

先封装成字典

image

字典再返回到前端 需要明确现在是Js前端跟python后端交互 能与前端交互的唯一方式就是json格式数据 字典得用JsonResponse序列化成json字符串格式再返回到前端

有了字典 用JsonResponse返回出去

image

结果:

image

前端看后端接口返回的数据:

bejson网站

image
)

聚合数据

而这样写的效率太低了 Django就专门开发了写接口的工具

Django自带 叫序列化组件(数据序列化将数据弄成json格式大字典) 这只是一个过渡 后续有drf

导一个序列化模块

image

结果:

image

ORM批量操作数据(ORM操作优化)

def ab_bk_func(request):
    # 1.往books表中插入10万条数据
    # for i in range(1, 100000):
    #     models.Books.objects.create(title='第%s本书' % i)
    """直接循环插入 10s 500条左右"""
    book_obj_list = []  # 可以用列表生成式[... for i in ... if ...]     生成器表达式(... for i in ... if ...)
    for i in range(1, 100000):
        book_obj = models.Books01(title='第%s本书' % i)  # 单纯的用类名加括号产生对象
        book_obj_list.append(book_obj)
    # 批量插入数据
    models.Books01.objects.bulk_create(book_obj_list)
    """使用orm提供的批量插入操作 5s 10万条左右"""
    # 2.查询出所有的表中并展示到前端页面
    book_queryset = models.Books01.objects.all()
    return render(request, 'BkPage.html', locals())

当在访问这个路由的时候往book表中插入十万条数据

直接循环插入数据 并展示到前端页面

image

一直在加载

image

10s才500条数据

而ORM提供了一个更加快捷的方式 可以批量插入 调bluk_create

image

结果:

image

5秒就十万条

分页器思路

分页器主要听处理逻辑 代码最后很简单 
推导流程
	1.queryset支持切片操作(正数)
	2.研究各个参数之间的数学关系
 		每页固定展示多少条数据、起始位置、终止位置
 	3.自定义页码参数
    	current_page = request.GET.get('page')
 	4.前端展示分页器样式
	5.总页码数问题
    	divmod方法
 	6.前端页面页码个数渲染问题
    	后端产生 前端渲染

数据不能可能全部展示 引申分页 不可能全展示

思维过程:

queryset支持切片操作

image

2.再研究各个参数之间的数学关系:

每页展示多少 起始位置 终止

image

三者关系

image

image

路由问号后面携带的参数的形式来获取当前页数 get请求获取

还需要自定义页码参数:输的不是数字页数可能报错 异常处理如输的不是数字让当前为1

image

前端分页器:ip和端口自动加

image

总页码数怎么渲染?

获取到底有多少?divmod方法

image

判断余数为TRUE加一

image

怎么动态展示?

image

传到后端去再传递前端

image

image

image

这么长页码 怎么优化

image

image

结果

image

渲染一下

image

当左端点5呢?

image

然而是不需要自己写的 有封装写好的 自带封装但使用很麻烦

我们可以自己封装 将自己写的分页器拷贝

自定义分页器的使用

django自带分页器模块但是使用起来很麻烦 所以我们自己封装了一个

只需要掌握使用方式即可

def ab_pg_func(request):
    book_queryset = models.Books01.objects.all()
    from app01.utils.mypage import Pagination
    current_page = request.GET.get('page')
    page_obj = Pagination(current_page=current_page, all_count=book_queryset.count())
    page_queryset = book_queryset[page_obj.start:page_obj.end]
    return render(request, 'pgPage.html', locals())


{% for book_obj in page_queryset %}
   <p>{{ book_obj.title }}</p>
{% endfor %}
{{ page_obj.page_html|safe }}

自定义分页器封装代码

class Pagination(object):
    def __init__(self, current_page, all_count, per_page_num=2, pager_count=11):
        """
        封装分页相关数据
        :param current_page: 当前页
        :param all_count:    数据库中的数据总条数
        :param per_page_num: 每页显示的数据条数
        :param pager_count:  最多显示的页码个数
        """
        try:
            current_page = int(current_page)
        except Exception as e:
            current_page = 1
 
        if current_page < 1:
            current_page = 1
 
        self.current_page = current_page
 
        self.all_count = all_count
        self.per_page_num = per_page_num
 
        # 总页码
        all_pager, tmp = divmod(all_count, per_page_num)
        if tmp:
            all_pager += 1
        self.all_pager = all_pager
 
        self.pager_count = pager_count
        self.pager_count_half = int((pager_count - 1) / 2)
 
    @property
    def start(self):
        return (self.current_page - 1) * self.per_page_num
 
    @property
    def end(self):
        return self.current_page * self.per_page_num
 
    def page_html(self):
        # 如果总页码 < 11个:
        if self.all_pager <= self.pager_count:
            pager_start = 1
            pager_end = self.all_pager + 1
        # 总页码  > 11
        else:
            # 当前页如果<=页面上最多显示11/2个页码
            if self.current_page <= self.pager_count_half:
                pager_start = 1
                pager_end = self.pager_count + 1
 
            # 当前页大于5
            else:
                # 页码翻到最后
                if (self.current_page + self.pager_count_half) > self.all_pager:
                    pager_end = self.all_pager + 1
                    pager_start = self.all_pager - self.pager_count + 1
                else:
                    pager_start = self.current_page - self.pager_count_half
                    pager_end = self.current_page + self.pager_count_half + 1
 
        page_html_list = []
        # 添加前面的nav和ul标签
        page_html_list.append('''
                    <nav aria-label='Page navigation>'
                    <ul class='pagination'>
                ''')
        first_page = '<li><a href="?page=%s">首页</a></li>' % (1)
        page_html_list.append(first_page)
 
        if self.current_page <= 1:
            prev_page = '<li class="disabled"><a href="#">上一页</a></li>'
        else:
            prev_page = '<li><a href="?page=%s">上一页</a></li>' % (self.current_page - 1,)
 
        page_html_list.append(prev_page)
 
        for i in range(pager_start, pager_end):
            if i == self.current_page:
                temp = '<li class="active"><a href="?page=%s">%s</a></li>' % (i, i,)
            else:
                temp = '<li><a href="?page=%s">%s</a></li>' % (i, i,)
            page_html_list.append(temp)
 
        if self.current_page >= self.all_pager:
            next_page = '<li class="disabled"><a href="#">下一页</a></li>'
        else:
            next_page = '<li><a href="?page=%s">下一页</a></li>' % (self.current_page + 1,)
        page_html_list.append(next_page)
 
        last_page = '<li><a href="?page=%s">尾页</a></li>' % (self.all_pager,)
        page_html_list.append(last_page)
        # 尾部添加标签
        page_html_list.append('''
                                           </nav>
                                           </ul>
                                       ''')
        return ''.join(page_html_list)

新建目录utils py文件存储

image

只需传 总页数 当前页及其他的按默认来也可以去改

image

切片操作

image

传到页面

image

传切片之后的到前端

image

form组件

前戏

获取用户数据并发送给后端校验

需求:后端获取前端发送过来的数据 要再屁股后面展示出是否校验是否正确

定义个字典一旦发送post请求或者get就会对字典里的值做修改 那么一旦用户输入的是jason或者123 那么就修改了字典里值然后再返回到页面

image

前端写form表单 再在后面上加span标签

image

一旦发送的是post就会判断输入的是不是jason 或123 如是对字典键做修改返回页面

image

form组件校验数据

小需求:获取用户数据并发送给后端校验 后端返回不符合校验规则的提示信息
    
form组件
	1.自动校验数据
	2.自动生成标签
	3.自动展示信息
    
from django import forms


class MyForm(forms.Form):
    username = forms.CharField(min_length=3, max_length=8)  # username字段最少三个字符最大八个字符
    age = forms.IntegerField(min_value=0, max_value=200)  # 年龄最小0 最大200
    email = forms.EmailField()  # 必须符合邮箱格式
    
 
校验数据的功能(初识)
	 form_obj = views.MyForm({'username':'jason','age':18,'email':'123'})
    form_obj.is_valid()  # 1.判断数据是否全部符合要求
    False  # 只要有一个不符合结果都是False
    form_obj.cleaned_data  # 2.获取符合校验条件的数据
    {'username': 'jason', 'age': 18}
    form_obj.errors  # 3.获取不符合校验规则的数据及原因
    {'email': ['Enter a valid email address.']}
1.只校验类中定义好的字段对应的数据 多传的根本不做任何操作
2.默认情况下类中定义好的字段都是必填的

前后端结合时 form组件把以上都做了

1.只校验类中定义好的字段对应的数据 多传的根本不做任何操作
2.默认情况下类中定义好的字段都是必填的

提前写好规范 导form模块

image

is_valid判断所有数据是否合法 只要一个不符合结果都是False

image

cleaned_data自动划分符合校验条件的数据

image

errors查看不符合的原因

image

原理是

image

正常情况
image

极端情况 当传多个 只会校验对应的数据

image

极端情况 少传了 直接报错 定好就必须要传

image

标签:models,self,Django,current,book,组件,序列化,pager,page
From: https://www.cnblogs.com/xiao-fu-zi/p/16995012.html

相关文章