内容概要
- django自带的序列化组件
- 批量数据操作
- 分页器推导流程
- 自定义分页器使用方法
- 校验性组件之forms组件
django自带的序列化组件serializers
| from app01 import models |
| from django.http import JsonResponse |
| from django.core import serializers |
| def d_data(request): |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| user_queryset = models.User.objects.all() |
| |
| ret = serializers.serialize('json', user_queryset) |
| return HttpResponse(ret) |
批量数据操作bulk_create方法
| '''循环插入''' |
| def many_data(request): |
| |
| |
| |
| |
| '''bulk_create 批量插入''' |
| book_list = [] |
| for i in range(100000): |
| |
| source_book_obj = models.Books(title=f'第{i}本书') |
| |
| book_list.append(source_book_obj) |
| models.Books.objects.bulk_create(book_list) |
| book_queryset = models.Books.objects.all() |
| return render(request,'many_data.html',locals()) |
| """ |
| 循环插入代码书写完毕后启动django后端,浏览器访问,会发现浏览器会有一个明显的卡顿等待时间,这不是你的浏览器有问题也不是网速有问题,而是后端再不停的操作数据库,耗时较长,大概需要等待一段时间之后才能正常看到刚刚插入的1000条数据,很明显这样操作数据库的效率太低 |
| bulk_create批量插入代码修改完毕之后,重启django项目浏览器重新访问,你会立马发现数据量增大十倍的情况下页面出现的速度居然还比上面的版本要快上速度倍!!! |
| bulk_create方法是django orm特地提供给我们的方便批量操作数据库的方式,效率非常高!!! |
| """ |
分页器推导流程
| """ |
| django本身也自带了一个分页器 只是不好用 所以我们自己写!!! |
| """ |
| |
| 网站不可能将所有的数据全部展示到一页,应该考虑使用分页 每页展示一些 |
| 1.all()结果集支持正数的索引切片 |
| 2.分页相关参数数学关系 |
| 3.后端渲染前端分页代码 |
| 4.后端限制分页展示数量 |
| 5.当页面小于6或者大于N都需要额外限制 |
| ... |
| 以后可能很多地方都需要使用分页 不可能重复编写 所以封装成了模块 |
| |
| 更多知识:https://www.cnblogs.com/Dominic-Ji/articles/12035722.html |
自定义分页器封装代码
| 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): |
| |
| if self.all_pager <= self.pager_count: |
| pager_start = 1 |
| pager_end = self.all_pager + 1 |
| |
| else: |
| |
| if self.current_page <= self.pager_count_half: |
| pager_start = 1 |
| pager_end = self.pager_count + 1 |
| |
| |
| 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 = [] |
| |
| 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) |
后端代码
| from utils import mypage |
| book_queryset = models.Books.objects.all() |
| |
| page_obj = mypage.Pagination(current_page=request.GET.get('page'),all_count=book_queryset.count()) |
| |
| page_queryset = book_queryset[page_obj.start:page_obj.end] |
| return render(request,'many_data.html',locals()) |
前端代码
| {% for book_obj in page_queryset %} |
| <p>{{ book_obj.title }}</p> |
| {% endfor %} |
| {{ page_obj.page_html|safe }} |


前戏
| |
| 编写一个校验用户名和密码是否合法的功能 |
| 前端需要自己编写获取用户数据的各种标签 |
| 前端需要自己想方设法的展示错误的提示信息 |
| 后端需要自己想方设法的编写校验代码(很多if判断) |
| |
| |
| 上面的三件事有一个人可以一次性帮你搞定>>>:form组件 |
| 1.数据校验 |
| 2.标签渲染 |
| 3.展示信息 |
| |
基本使用
| |
| from django import forms |
| class MyForm(forms.Form): |
| |
| username = forms.CharField(min_length=3,max_length=8) |
| |
| age = forms.IntegerField(min_value=0,max_value=150) |
| |
| email = forms.EmailField() |
数据校验
| from app01 import views |
| |
| form_obj =MyForm({'username':'jason','age':18,'email':'123qq'}) |
| |
| form_obj.is_valid() |
| |
| form_obj.errors |
| {'email': ['Enter a valid email address.']} |
| |
| form_obj.cleaned_data |
| {'username': 'jason', 'age': 18} |
| |
| """ |
| 1.forms类中所有的字段数据默认都是必填的 不能少 |
| 如果想忽略某些字段 可以添加 required=False |
| eg: |
| email = forms.EmailField(required=False) |
| 2.forms类中额外传入的字段数据不会做任何的校验 直接忽略 |
| """ |
渲染标签
| 渲染方式1:封装程度高 扩展性较差 主要用于快速生成页面测试功能 |
| {{ form_obj.as_p }} |
| {{ form_obj.as_table }} |
| {{ form_obj.as_ul }} |
| 渲染方式2:封装程度低 扩展性较好 但是字段比较多的情况下不方便 |
| {{ form_obj.username.label }} |
| {{ form_obj.username }} |
| 渲染方式3:推荐使用!!! |
| {% for form in form_obj %} |
| <p> |
| {{ form.label }} |
| {{ form }} |
| </p> |
| {% endfor %} |
| """ |
| forms组件只负责渲染获取用户数据的标签 |
| form表单标签和提交按钮需要自己写 |
| |
| 渲染标签中文提示 可以使用参数 label指定 不指定默认使用字段名首字母大写 |
| """ |
展示信息
| """ |
| forms类中填写的校验性参数前端浏览器会识别并添加校验操作 |
| 但是前端的校验是可有可无的 不能指望它!!! 后端必须要有 |
| |
| form表单可以取消浏览器自动添加校验功能的操作 |
| <form action="" method="post" novalidate></form> |
| """ |
| {{ form.errors.0 }} |
| |
| 提示信息可以自定义 |
| username = forms.CharField(min_length=3,max_length=8,label='用户名', |
| error_messages={ |
| 'min_length':'用户名最短3位', |
| 'max_length':'用户名最长8位', |
| 'required':'用户名必填' |
| }) |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?