Django-分页-form数据校验
分页
view层
def fenye(request):
all_data = models.AuthorDetail.objects.all()
current_page = request.GET.get('page',1)
count = all_data.count()
page_obj = Pagination(current_page=current_page,all_count=count)
data = all_data[page_obj.start:page_obj.end]
return render(request,'fenye.html',locals())
模板层
{% for a in data %}
<p>{{ a.addr }}</p>
{% endfor %}
{{ page_obj.page_html|safe }}
自定义分页器
class Pagination(object):
def __init__(self, current_page, all_count, per_page_num=10, pager_count=11):
"""
封装分页相关数据
:param current_page: 当前页
:param all_count: 数据库中的数据总条数
:param per_page_num: 每页显示的数据条数
:param pager_count: 最多显示的页码个数
用法:
queryset = model.objects.all()
page_obj = Pagination(current_page,all_count)
page_data = queryset[page_obj.start:page_obj.end]
获取数据用page_data而不再使用原始的queryset
获取前端分页样式用page_obj.page_html
"""
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)
form表单校验组件
由于校验的安全性,前端可以没有校验,但是后端必须校验
自定义组件
from django import forms
from app01 import models
class myzx(forms.Form):
username = forms.CharField(min_length=3, max_length=8, label='用户名',
error_messages={
'min_length': '用户名不能少于三位',
'max_length': '用户名不能大于八位',
'required': '用户名不能为空',
}, widget=forms.widgets.TextInput(attrs={'class': 'form-control'})
)
password = forms.CharField(min_length=3, max_length=8, label='密码',
error_messages={
'min_length': '密码不能少于三位',
'max_length': '密码不能大于八位',
'required': '密码不能为空',
}, widget=forms.widgets.PasswordInput(attrs={'class': 'form-control'})
)
confirm_password = forms.CharField(min_length=3, max_length=8, label='确认密码',
error_messages={
'min_length': '确认密码不能少于三位',
'max_length': '确认密码不能大于八位',
'required': '确认密码不能为空',
}, widget=forms.widgets.PasswordInput(attrs={'class': 'form-control'})
)
email = forms.EmailField(
label='邮箱',
error_messages={
'required': '邮箱不能为空',
'invalid': '邮箱格式不正确'
}, widget=forms.widgets.EmailInput(attrs={"class": 'form-control'})
)
前端表单可以自己写,也可以使用组件提供的
obj为自己定义的组件对象
<form method="POST">
<p>{{ obj.username }}</p>
<p>{{ obj.confirm_password }}</p>
<p>{{ obj.confirm_password }}</p>
<p>{{ obj.email }}</p>
<input type="submit" value="提交">
</form>
但是这样渲染,会默认加上前端的校验,但是加在前端是不安全的,所以不采用
<form method="POST">
<p><input type="text" name="username" class="form-control" maxlength="8" minlength="3" required="" id="id_username"></p>
<p><input type="password" name="confirm_password" class="form-control" maxlength="8" minlength="3" required="" id="id_confirm_password"></p>
<p><input type="password" name="confirm_password" class="form-control" maxlength="8" minlength="3" required="" id="id_confirm_password"></p>
<p><input type="email" name="email" class="form-control" required="" id="id_email"></p>
<input type="submit" value="提交">
</form>
要在form表单上加上novalidate,可以取消上面的功能
<form method="POST" novalidate>
校验上传的数据
#验证数据,获取验证结果对象
form_obj = myforms.MyRegForm(request.POST)
#判断是否全部验证成功
if form_obj.is_valid():
#用户提交的数据(字典形式的字段和字段值)
print(form_obj.cleaned_data)
else:
#用户提交错误的数据(错误信息为带前端样式的错误字段和错误描述信息)
#是一个字典,上面的打印信息时重写了str的原因
print(form_obj.errors)
半完成版小案例
前端
obj.errors.username.0,才能拿到不带前端标签,完整的错误描述
<form method="POST" novalidate>
<p>{{ obj.username.label }}{{ obj.username }}{{ obj.errors.username.0 }}</p>
<p>{{ obj.password.label }}{{ obj.password }}{{ obj.errors.password.0 }}</p>
<p>{{ obj.confirm_password.label }}{{ obj.confirm_password }}{{ obj.errors.confirm_password.0 }}</p>
<p>{{ obj.email.label }}{{ obj.email }}{{ obj.errors.email.0 }}</p>
<input type="submit" value="提交">
</form>
后端
可以通过这个简便的实现数据提交,form的内容还在,因为obj记录下来数据了
其实后端返回的都是obj对象,只是最开始的那个是没有数据的,所以主要起渲染界面用
将数据传上去后,生成的那个对象是带数据的,所以会携带错误信息并渲染到前端,两个obj是不同的
def text(request):
if request.method == 'GET':
obj = myforms.myzx()
return render(request,'zx.html',locals())
else:
obj = myforms.myzx(request.POST)
if obj.is_valid():
#打印验证成功的数据,即使数据有错也能打印,只打印验证通过的
print("验证成功",obj.cleaned_data)
return HttpResponse("数据校验成功")
else:
print("验证失败",obj.errors)
print(type(obj.errors))
return render(request,'zx.html',locals())
forms数据添加
在写forms约束的时候我们可以把字段名和models里面涉及的一样,这样的话,clean_data的数据字典就完全符合提交数据的要求了
#这样的话,数据就不用一条一条的取出来了,可以一次性提交数据
if obj.is_valid():
models.books.objects.create(**obj.cleaned_data)
forms数据编辑
编辑界面需要元数据的内容,那么就可以使用校验功能,然后把数据返回前台,而且数据是从数据库拿去的数据是不会有问题的,前端的样式和add差不多
def edit_user(request,nid):
if request.method == 'GET':
#获取数据
data = models.UserInfo.objects.filter(pk=nid).first()
#传给forms,因为它可以自动生成html
obj = UserForm({'username':data.username,'email':data.email})
return render(request,'edit_user.html',locals())
#else为修改数据的请求
else:
obj = UserForm(request.POST)
if obj.is_valid():
models.UserInfo.objects.filter(pk=id).update(**obj.cleaned_data)
return redirect('/users/')
else:
return render(request,'edit_user.html')
form字段大全
https://www.cnblogs.com/xiaoyuanqujing/articles/11753466.html
其中weight是生成前端代码的重要插件
返回参数为数字的单选框
zx = fields.ChoiceField(
choices = [(1,'钱'),(2,'权')]
)
动态获取元数据
一
刷新界面会执行这些代码,相当于重新去数据库取值
hobby = forms.IntegerField(
label='爱好',
widget=widgets.Select()
)
def __init__(self,*args,**kwargs):
super(myzx,self).__init__(*args,**kwargs)
print(models.Blog.objects.values_list('id','site_title'))
#注意这句要写后面,否则会被super覆盖掉值
self.fields['hobby'].widget.choices = models.Blog.objects.values_list('id','site_title')
二
from django.forms.models import ModelChoiceField
hobby2 = ModelChoiceField(
label='爱好2',
#是显示的数据部分,想要指定显示内容需要去重写models的str方法
queryset=models.Blog.objects.all(),
#只是显示value值,上传是使用的
to_field_name='id'
)
from前端html生成简写-高级
但是不推荐,自定制比较弱
{{obj.as_p}}
<ul>
{{obj.as_ul}}
</ul>
<table>
{{obj.as_table}}
</table>
前端字符串转标签
from django.utils safestring import mark_safe
txt = mark_safe(txt)
钩子函数
注意这些函数都要写在form类中
局部钩子函数
给部分字段加强校验
def clean_username(self):
username = self.cleaned_data.get('username')
if '88' in username:
self.add_error('username','名字不能包含88')
return username
全局钩子函数
针对多个字段校验使用全局钩子函数
def clean(self):
password = self.cleaned_data.get('password')
re_password = self.cleaned_data.get('re_password')
if not password == re_password:
self.add_error('re_password','密码不相等啊')
return self.cleaned_data
正则和其他表单数据提交
#
# phone = forms.CharField(label='手机号',validators=[RegexValidator(r'^[0-9]+$', '请输入数字'), RegexValidator(r'^159[0-9]+$', '数字必须以159开头')])
#
#
#
# """下面的是了解知识点 你只需要整理到你的博客中 到时候需要用 直接来拷贝即可"""
#
# gender = forms.ChoiceField(
# choices=((1, "男"), (2, "女"), (3, "保密")),
# label="性别",
# initial=3,
# widget=widgets.RadioSelect()
# )
#
#
#
#
# hobby = forms.ChoiceField(
# choices=((1, "篮球"), (2, "足球"), (3, "双色球"),),
# label="爱好",
# initial=3,
# widget=widgets.Select()
# )
#
# hobby1 = forms.MultipleChoiceField(
# choices=((1, "篮球"), (2, "足球"), (3, "双色球"),),
# label="爱好",
# initial=[1, 3],
# widget=widgets.SelectMultiple()
# )
#
# keep = forms.ChoiceField(
# label="是否记住密码",
# initial="checked",
# widget=forms.widgets.CheckboxInput()
# )
#
# hobby2 = forms.MultipleChoiceField(
# choices=((1, "篮球"), (2, "足球"), (3, "双色球"),),
# label="爱好",
# initial=[1, 3],
# widget=forms.widgets.CheckboxSelectMultiple()
# )
Django-分页-form数据校验的更多相关文章
- Django之form组件自动校验数据
目录 一.form介绍 二.普通方式手写注册功能 views.py register.html 三.使用form组件实现注册功能 views.py register2.html 四.pycharm的专 ...
- Django---form表单提交数据到数据库(普通方法+Django的form类)
目标: ①.初始form的简单应用 ②.使用Django的form组件完成新增一个帖子 方法一:普通方法 1.前端表单代码 <div> <form class="navba ...
- Laravel Form 表单的数据校验
例如,要使用手机号加验证码的方式提供登录网站的功能,那么在处理前端提交的 form 表单时,就不得不对提交的手机号及验证码做基本的数据校验. 手写规则,非常浪费时间.使用 laravel 内置的 va ...
- Django 分页查询并返回jsons数据,中文乱码解决方法
Django 分页查询并返回jsons数据,中文乱码解决方法 一.引子 Django 分页查询并返回 json ,需要将返回的 queryset 序列化, demo 如下: # coding=UTF- ...
- django 使用form组件提交数据之form表单提交
django的form组件可以减少后台在进行一些重复性的验证工作,极大降低开发效率. 最近遇到一个问题: 当使用form表单提交数据后,如果数据格式不符合后台定义的规则,需要重新在前端页面填写数据. ...
- Django之DRF源码分析(二)---数据校验部分
Django之DRF源码分析(二)---数据校验部分 is_valid() 源码 def is_valid(self, raise_exception=False): assert not hasat ...
- Django day26 HyperlinkedIdentityField,序列化组件的数据校验以及功能的(全局,局部)钩子函数,序列化组件的反序列化和保存
一:HyperlinkedIdentityField(用的很少):传三个参数:第一个路由名字,用来反向解析,第二个参数是要反向解析的参数值,第三个参数:有名分组的名字 -1 publish = ser ...
- Django--分页器(paginator)、Django的用户认证、Django的FORM表单
分页器(paginator) >>> from django.core.paginator import Paginator >>> objects = ['joh ...
- Django之 Form和ModelForm组件
01-Form介绍 我们之前在HTML页面中利用form表单向后端提交数据时,都会写一些获取用户输入的标签并且用form标签把它们包起来. 与此同时我们在好多场景下都需要对用户的输入做校验,比如校验用 ...
随机推荐
- Net Framework,Net Core 和 Net Standard 区别
前几天我在一个群里看到有关这方面的讨论,最后感觉讨论的不是很清晰,有幸的是我们的项目去年就开始迁移NetCore的调研了,我个人多多少少也是有过这方面的研究.下面我将说一下我自己对着三个的认识如果有不 ...
- 盘点一下Creator星球上的开源工具包!
晓衡开始写公众号,最早是从上架 Cocos 商店的 pbkiller 插件开始的,到至今有2年2个月了.在这期间,又陆续在公众号上分享了多个实用工具包,在这里统一盘点一下,方便与大家交流学习. 一.u ...
- 在VMware下进行的使用ssh服务管理远程主机
基于密钥的安全验证--sshd服务的配置文件解析(两台linux) 首先你有两台虚拟机 并且能够ping通(该实验的目的是通过客户端访问服务端) 打开终端进入到这个界面 看一下服务 如果有这三个服 ...
- 汇编实战准备:DOS调用命令
mov dx,offset message mov ah, int 21h 将message的偏移地址赋值给dx,之后 MOV AH,9 INT 21H 调用DOS功能,该功能为显示打印DS:DX地址 ...
- 最小生成树两个经典算法(Prime算法、Kruskal算法) - biaobiao88
经典的最小生成树例子,Prime算法,具体的步骤及其注释本人均在代码中附加,请仔细阅读与品味,要求,可以熟练的打出. //Prime算法基础 #include<iostream> usin ...
- 用css或js实现文本输入框的特效
1文本框默认点击特效: 点击文本框,外围会出现蓝色阴影,取消该特效,为该文本框添加css样式"outline:none;",就取消了默认特效. 2实现百度搜索框点击特效: 点击文本 ...
- .netcore之DI批量注入(支持泛型) - xms
一旦系统内模块比较多,按DI标准方法去逐个硬敲AddScoped/AddSingleton/AddTransient缺乏灵活性且效率低下,所以批量注入提供了很大的便捷性,特别是对于泛型的服务类,下面介 ...
- python入门之五种字典创建方法
a = dict(one = 1, tow = 2, three = 3)b = {'one' :1,'tow' :2 , 'three' :3}c = dict (zip(['one', 'tow' ...
- tslib1.1移植
安装步骤: 1.准备工作确保以下软件已安装 # apt-get install autoconf(或autoconf2.13)# apt-get install automake# apt-get i ...
- 对于 TCP 三次握手的理解
假设名叫 A 和 B 的两个人要进行通信,那么他们两人之间,首先要确保通信顺畅. 而确保通信顺畅,就要从 3 个维度,确定 8 个能力 3 个维度分别是: 1.人知道(A 知道.B 知道) 2.人(A ...