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标签把它们包起来. 与此同时我们在好多场景下都需要对用户的输入做校验,比如校验用 ...
随机推荐
- Django实现WebSSH操作物理机或虚拟机
我想用它替换掉xshell.crt之类的工具 WebSSH操作物理机或虚拟机 Django实现WebSSH操作Kubernetes Pod文章发布后,有小伙伴说咖啡哥,我们现在还没有用上Kuberne ...
- 再整理:Visual Studio Code(vscode)下的通用C语言环境搭建
版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://www.cnblogs.com/czlhxm/p/11794743.ht ...
- Flex简记
display的flex属性的使用对象分为1.容器即包含有元素的元素,2.项目,即某一个元素.就容器而言,flex可以实现换行(flex-wrap),改变容器内元素的排列方向(flex-directi ...
- 七月月赛T1
题目背景 借助反作弊系统,一些在月赛有抄袭作弊行为的选手被抓出来了! 题目描述 现有 2^n\times 2^n (n\le10)2n×2n(n≤10) 名作弊者站成一个正方形方阵等候 kkksc03 ...
- windows使用docker运行mysql等工具(二)安装运行mysql
今天接着上一篇的内容继续来学习安装运行mysql.建议先阅读第一篇:windows安装docker 一 查看mysql版本 如果想知道mysql镜像具体有哪几个版本,需要去docker hub查看. ...
- python入门之五种字典创建方法
a = dict(one = 1, tow = 2, three = 3)b = {'one' :1,'tow' :2 , 'three' :3}c = dict (zip(['one', 'tow' ...
- PHP关于access_token失效问题
PHP关于access_token失效问题 有时候PHP设置了缓存 明明就是没有过期 但却提示失效这情况一般就是1 多个appid和secrete 生成的access_token互相覆盖了 所以 这种 ...
- Scss的使用场景
一.Scss 1.CSS有几个缺点 语法不够强大,没有变量和合理的样式复用机制 使得逻辑上相关的属性值必须以字面的形式重复输出,难以维护 动态的样式语言为css富裕了动态语言的特性 极大的提高了样式语 ...
- DHCP动态管理主机地址
步骤一:搭建环境 需要Windows 2008 R2 系统 (DHCP服务端)以及 CentOS7 系统客户机(DHCP客户机) 安装DHCP服务程序(这里提示读者,一般安装好CentOS系统之后, ...
- 创建一个线程池(java)
private ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat("billService-poo ...