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标签把它们包起来. 与此同时我们在好多场景下都需要对用户的输入做校验,比如校验用 ...
随机推荐
- 关于Ubuntu10.04磁盘空间不足的问题
最近由于项目问题,需要自己写驱动,但是驱动知识太少,开始下了个内核自己玩玩,没想到的是内核下好了,Ubuntu待机后却登录不了了,重启了好几次也不行,而且颜色是蓝色,右上角还提示:Install pr ...
- Java类、对象、变量、方法
对象:有状态和行为.例如,一条狗是一个对象,它的状态有:颜色.名字.品种:行为有:摇尾巴.叫.吃等 类:类是一个模板,描述一类对象的行为和状态 对象的行为通过方法来体现,状态就是对象的属性,变量可以是 ...
- [开源]基于goapp+xterm实现webssh-网页上的SSH终端(golang)
简析 基于goapp+xterm实现webssh-网页上的SSH终端. 开源地址见文末. 特性 在网页上实现一个SSH终端.从而无需Xshell之类的模拟终端工具进行SSH连接. 可以对交互命令进行审 ...
- call 与apply深入
http://blog.csdn.net/bao19901210/article/details/21614761
- ITester软件测试小栈,快来点击领取你的能量值!
日供一卒,功不唐捐,这不是一个非正常更新的ITester软件测试小栈,不定期分享软件测试相关,包括功能.接口.自动化.性能.专项.测试开发,简历指点,面试助攻,群而不党,和而不同,如趋同,且同行.
- 怎么把CAT客户端的RootMessageId记录到每条日志中?
什么是RootMessageId? 为了理解RootMessageId先简单介绍一下CAT的数据结构设计.CAT客户端会将所有消息都封装为一个完整的消息树(MessageTree),消息树可能包括Tr ...
- 深入理解计算机系统 第三章 程序的机器级表示 part2
这周由于时间和精力有限,只读一小节:3.4.4 压入和弹出栈数据 栈是一种特殊的数据结构,遵循“后进先出”的原则,可以用数组实现,总是从数组的一端插入和删除元素,这一端被称为栈顶. 栈有两个常用指令 ...
- 更改微信小程序的组件默认样式
checkbox /*checkbox 整体大小 */ .checkbox { width: 12%; /* height: 240rpx; */ } /*checkbox 选项 ...
- [RAM] FPGA的学习笔记——RAM
1.RAM——随机存取存储器, 分为SRAM和DRAM. SRAM:存和取得速度快,操作简单.然而,成本高,很难做到很大.FPGA的片内存储器,就是一种SRAM,用来存放程序,以及程序执行过程中,产生 ...
- [LC]876题 Middle of the Linked List (链表的中间结点)(链表)
①中文题目 给定一个带有头结点 head 的非空单链表,返回链表的中间结点. 如果有两个中间结点,则返回第二个中间结点. 示例 1: 输入:[1,2,3,4,5]输出:此列表中的结点 3 (序列化形式 ...