139 分页器和django中的form校验

it2023-09-28  70

昨日回顾

1 ajax:异步的javascript的xml,同时可以发出很多ajax的请求,局部刷新 2 本质就是使用javascript这门语言发送http请求,(异步),原生,jquery的ajax方法,axios 3 如何使用(借助于jquery) # 默认编码方式是urlencoded $.ajax({ url:/books/?name=lqz, method:'post/get', data:{name:'lqz',age:19}, success:function (data){ 打印,弹窗,渲染页面(js dom操作,修改页面) } }) 4 上传文件 var formdata=new Formdata() formdata.append('name','lqz') formdata.append('myfile',$('#id_file')[0].files[0]) $.ajax({ url:/books/?name=lqz, method:'post/get', processData:false, contentType:false, data:formdata, success:function (data){ 打印,弹窗,渲染页面(js dom操作,修改页面) } }) # 后端代码写一套即可:使用form表单传,postman,ajax传,都是一样的 5 上传json格式 $.ajax({ url:/books/?name=lqz, method:'post/get', contentType:'application/json', data:字符串(json格式), success:function (data){ 打印,弹窗,渲染页面(js dom操作,修改页面) } }) 6 后端返回数据 -HttpResponse:它没有指定,text/html -JsonResponse:它指定了响应编码:application/json -ajax方法:会去看响应编码是什么,如果是application/json,自动调用JSON.parser(),如果不是json格式,就不处理 -于是:success:function (data) 可能是个字符串,也可能是个对象,响应编码决定的 7 js中json序列化和反序列化 -JSON.parser() -JSON.stringify(data) 8 django内置的序列化器 -需要会自己转(把对象转成json格式) -自己写(局限性,以后再转publish,还得再写一遍,不通用) ll=[] for book in book_list: ll.append({'name':book.name,'age':book.age}) return JsonResponse(ll,safe=False) {name:lqz,age:18,hobbys:[{hobbyname:'篮球',hobbyid:1},{hobbyname:'足球',hobbyid:2}]} [{name:lqz,age:18},{name:egon,age:18},{name:zs,age:18}]

今日内容

# 批量插入数据 l=[] for i in range(100): book = models.Book(name=f'书{i}', price=i) l.append(book) models.Book.objects.bulk_create(l,10) #### 数据库查询的顺序 #### class Meta: ordering = ('id',) # 默认id排序

1 分页器组件介绍

1 项目数据量大了以后,涉及到分页,一页一页的加载显示 2 django中分页器组件,把分页常用的东西,封装到一个类中 3 实例化一个对象,对象里有属性和方法 # 分页器对象和页对象的一些用法 from django.core.paginator import Paginator def func139_1(request): book_list = models.Book.objects.all() # 实例化得到对象 # 第一个参数:要分页的数据,book_list # 第二个参数:每页条数 paginator = Paginator(book_list, 10) # Paginator对象的属性和方法 print(paginator.per_page) # 每页显示的条数 -- 10 print(paginator.count) # 总条数,总共要分页多少条数据 print(paginator.num_pages) # 总页码数 print(paginator.page_range) # 页码的生成器[1,2,3....10] page= paginator.page(2) # 每一页的对象page,属性和方法 print(page.has_next()) # 是否有下一页 print(page.next_page_number()) # 下一页页码 print(page.has_previous()) # 是否有上一页 print(page.previous_page_number()) # 上一页的页码,没有就报错 print(page.object_list) # 当前页的数据 print(page.number) # 当前页数 return render(request, 'func139_1.html', locals())

2 分页器的简单使用

## views.py def index(request): # 需要的第三个参数 page_num_int=int(request.GET.get('page',1)) book_list = models.Book.objects.all() paginator = Paginator(book_list, 10) # 需要的第一个参数:页码的生成器 [1,2,3,4,5,6,7,8,9,10] page_range = paginator.page_range # 需要的第二个参数,去到某一页的page对象 page = paginator.page(page_num_int) return render(request, 'index.html', {'page_range':page_range,'page':page,'page_num_int':page_num_int}) <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <link rel="stylesheet" href="/static/bootstrap/css/bootstrap.min.css"> <title>Title</title> </head> <body> <div class="container-fluid"> <div class="row"> <div class="col-md-6 col-md-offset-3"> <table class="table"> <thead> <tr> <th>id</th> <th>名字</th> <th>价格</th> </tr> </thead> <tbody> {% for book in page.object_list %} <tr> <td>{{ book.id }}</td> <td>{{ book.name }}</td> <td>{{ book.price }}</td> </tr> {% endfor %} </tbody> </table> <div class="text-center"> <nav aria-label="Page navigation"> <ul class="pagination"> {% if page.has_previous %} <li> <a href="/?page={{ page.previous_page_number }}" aria-label="Previous"> <span aria-hidden="true">&laquo;</span> </a> </li> {% else %} <li class="disabled"> <a href="" aria-label="Previous"> <span aria-hidden="true">&laquo;</span> </a> </li> {% endif %} {% for page_num in page_range %} {% if page_num_int == page_num %} <li class="active"><a href="/?page={{ page_num }}">{{ page_num }}</a></li> {% else %} <li><a href="/?page={{ page_num }}">{{ page_num }}</a></li> {% endif %} {% endfor %} {% if page.has_next %} <li> <a href="/?page={{ page.next_page_number }}" aria-label="Next"> <span aria-hidden="true">&raquo;</span> </a> </li> {% else %} <li class="disabled"> <a href="" aria-label="Next"> <span aria-hidden="true">&raquo;</span> </a> </li> {% endif %} </ul> </nav> </div> </div> </div> </div> </body> </html>

3 分页器进阶使用

# 最多显示前5 后5 和当前,总共11个页码,如果少于11,全部显示出来 #逻辑分析 显示左5,右5,总共11个页, 1 如果总页码大于11 1.1 if 当前页码减5小于1,要生成112的列表(顾头不顾尾,共11个页码) page_range=range(1,12) 1.2 elif 当前页码+5大于总页码,生成当前页码减10,到当前页码加1的列表(顾头不顾尾,共11个页码) page_range=range(paginator.num_pages-10,paginator.num_pages+1) 1.3 else 生成当前页码-5,到当前页码+6的列表 page_range=range(current_page_num-5,current_page_num+6) 2 其它情况,生成的列表就是pageinator的page_range page_range=paginator.page_range # views.py def index(request): # 需要的第三个参数 page_num_int = int(request.GET.get('page', 1)) book_list = models.Book.objects.all() paginator = Paginator(book_list, 1) # 需要的第一个参数:页码的生成器 [1,2,3,4,5,6,7,8,9,10] # page_range = paginator.page_range if paginator.num_pages > 11: # 当前条件符合了以后,有三种情况 if page_num_int - 5 < 1: page_range = range(1, 11) elif page_num_int + 5 > paginator.num_pages: page_range = range(paginator.num_pages - 10, paginator.num_pages + 1) else: page_range = range(page_num_int - 5, page_num_int + 5) else: page_range = paginator.page_range # 需要的第二个参数,去到某一页的page对象 page = paginator.page(page_num_int) return render(request, 'index.html', {'page_range': page_range, 'page': page, 'page_num_int': page_num_int}) 模版文件同上

4 form组件介绍

1 注册功能,登陆功能,前段需要校验(字段长度,邮箱是否合法...) 2 前端校验可以没有,后端校验是必须的,使用传统方式,if判断写的很多 3 借助于forms组件 可以快速实现字段的校验() # app01下新建myforms.py from django import forms # 写一个类,继承forms.Form 写字段 class MyForm(forms.Form): # 校验这个字段,必填,最大长度32,最小长度是3 name = forms.CharField(required=True, max_length=32, min_length=3, label='用户名') # 校验邮箱地址 email = forms.EmailField(label='邮箱') # 校验年龄,最小0最大200 age= forms.IntegerField(max_value=200,min_value=0,label='年龄') # 一些问题: # 1 错误是英文的 # 2 错误信息是标签 # 3 更复杂的校验,name必须有大写,数字

5 form组件校验数据

# views.py def func139_2(request): # 数据可以是从前端传过来的,也可以是后端自己的数据 # 我现在有以下数据 data = {'name': 'lq', 'email': "3333"} # 校验数据是否合法 # 实例化得到form对象,把要校验的数据传入 form = myforms.MyForm(data=data) # 校验数据 if form.is_valid(): # 返回True或者False print('校验成功') # 校验通过的数据: print(form.cleaned_data) else: # 拿出校验通过的数据 print(form.cleaned_data) print('校验失败') # 哪个字段失败了? print(form.errors) # 重写了errors的__str__ print(type(form.errors)) print(form.errors.as_json()) print(form.errors.as_data()) # form.errors.as_ul()是为了渲染模版 return HttpResponse('ok')

6 forms渲染模版功能

## views.py def register(request): if request.method=='GET': form=myforms.MyForm() return render(request,'register.html',{'form':form}) elif request.method=='POST': # 数据校验 form=myforms.MyForm(request.POST) if form.is_valid(): print('校验通过,存数据库') else: print(form.errors.as_data()) print('校验失败,返回错误') return HttpResponse('ok') # 模版文件 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <hr> <h1>手动创建模板</h1> <form action="" method="post"> <p>用户名:<input type="text" name="name"></p> <p>邮箱:<input type="text" name="email"></p> <p>年龄:<input type="text" name="age"></p> <p><input type="submit" value="提交"></p> </form> <hr> <h1>半自动渲染模板1</h1> <form action="" method="post"> <p>用户名:{{ form.name }}</p> <p>邮箱:{{ form.email }}</p> <p>年龄:{{ form.age }}</p> <p><input type="submit" value="提交"></p> </form> <h1>半自动渲染模板2(用的最多)</h1> <form action="" method="post"> <p>{{ form.name.label }}--{{ form.name }}</p> <p>{{ form.email.label }}---{{ form.email }}</p> <p>{{ form.age.label }}---{{ form.age }}</p> <p><input type="submit" value="提交"></p> </form> <h1>半自动渲染模板3(用的最多)</h1> <form action="" method="post"> {% for foo in form %} <p>{{ foo.label }} :{{ foo }}</p> {% endfor %} <p><input type="submit" value="提交"></p> </form> <h1>全自动(了解)</h1> <form action="" method="post"> {# {{ form.as_ul }}#} {{ form.as_p }} {# <table>#} {# {{ form.as_table }}#} {# </table>#} <p><input type="submit" value="提交"></p> </form> </body> </html>

作业

## 0 整理笔记 ## 1 分页器实现通过传入某一页,和该页大小实现分页器 ## 2 用户注册: 通过forms实现半自动的渲染模板,校验字段,校验通过存到user(bootstrap样式) ## 3 (拓展)研究一些form如何校验更复杂的校验,name必须有大写,小写,数字,错误信息的中文显示 # 可以自定义中文显示 或者 在settings里改语言 name = forms.CharField(min_length=4, label="姓名", error_messages={"min_length": "太短了", "required": "该字段不能为空!"}) ## 4 拓展cookie,session,token ,jwt from django import forms from django.core.exceptions import ValidationError from app01 import models class EmpForm(forms.Form): name = forms.CharField(min_length=5, label="姓名", error_messages={"required": "该字段不能为空!", "min_length": "用户名太短。"}) age = forms.IntegerField(label="年龄") salary = forms.DecimalField(max_digits=5, decimal_places=2, label="工资") r_salary = forms.DecimalField(max_digits=5, decimal_places=2, label="请再输入工资") def clean_name(self): # 局部钩子 val = self.cleaned_data.get("name") if val.isdigit(): raise ValidationError("用户名不能是纯数字") elif models.Emp.objects.filter(name=val): raise ValidationError("用户名已存在!") else: return val def clean(self): # 全局钩子 确认两次输入的工资是否一致。 val = self.cleaned_data.get("salary") r_val = self.cleaned_data.get("r_salary") if val == r_val: return self.cleaned_data else: raise ValidationError("请确认工资是否一致。") views.py 文件代码: app01/views.py def add_emp(request): if request.method == "GET": form = EmpForm() # 初始化form对象 return render(request, "add_emp.html", {"form":form}) else: form = EmpForm(request.POST) # 将数据传给form对象 if form.is_valid(): # 进行校验 data = form.cleaned_data data.pop("r_salary") models.Emp.objects.create(**data) return redirect("/index/") else: # 校验失败 clear_errors = form.errors.get("__all__") # 获取全局钩子错误信息 return render(request, "add_emp.html", {"form": form, "clear_errors": clear_errors})
最新回复(0)