自定义表单提交筛选分页怎么做_form组件和自定义分页

本文介绍了如何在Django中不使用form组件实现简单的注册功能,包括前端页面渲染、数据校验和错误信息展示。接着讨论了使用form组件创建表单字段、设置验证规则和自定义样式。最后,讲解了自定义分页器的实现,包括初始化、数据切片和生成分页HTML。
摘要由CSDN通过智能技术生成

FORM组件

不利用form组件实现一个简陋的功能

需求

1.注册功能

用户输入的用户名中 不能包含'违规信息'

如果包含了 就提示用户 输入的内容不符合社会主义核心价值观

用户输入的密码 不能小于三位

如果密码少于三位 提示用户 密码太短了

(******)

校验数据通常是前后端都有校验

但是前端校验可有可无 哪怕再牛逼

后端也必须要有校验 反正一句话 前端可有不校验 后端必须校验!!!

思路

1.搭建前端页面 >>> 渲染页面

2.获取前端用户提交的数据校验 >>> 校验数据

3.对数据的校验的结果 展示到前端页面给用户查看 >>> 展示错误信息

# 后端

def reg(request):

back_dic = {"username":'','password':''}

if request.method == 'POST':

username = request.POST.get('username')

password = request.POST.get('password')

if '违规信息' in username:

# 提示信息

back_dic['username'] = '不符合社会主义核心价值观'

if len(password) < 3:

# 提示信息

back_dic['password'] = '密码不能少于三位'

return render(request,'reg.html',locals())

# 前端

username:

{{ back_dic.username }}

password:

{{ back_dic.password }}

使用form组件

定义一个类继承django 中的forms.Form类

在类中创建form组件字段

username = forms.CharField(min_length=3,max_length=8,max_length='用户名',

error_messages={

'min_length':'用户名最短三位',

'max_length':'用户名最长八位',

'required':'用户名不能为空'

},initial='我是初始值',required=False, widget=forms.widgets.TextInput(attrs={'class':'class值'})

)

# min_length char字段的最短长度

# max_length char字段的最长长度

# label 对象.字段.label获得的值,默认是首字母大写的字段名

# error_messages 错误信息的字典

{

'min_length':'不满足最短长度的错误信息',

'max_length':'不满足最长长度的错误信息',

'required':'文本框为空是的错误信息',

'invalid':'邮箱格式不正确时的展示信息',

}

# initial 设置文本框初始值,即前端的value

# required 默认为True,当为False时,意味着这个字段不传也可以通过,is_valid()也可以为True。但是只要你传了,就要校验

关于widget字段

# widget=forms.widgets.TextInput(attrs={'class':'class值'})

# 值一定为forms.widgets

# TextInput 规定里input的类型是text,还可以是其他

# attrs为这个input框添加属性,可以是类id样式js任意

如何改变input框的type属性值

widget= widgets.TextInput()

widget=widgets.PasswordInput()

如何让forms组件渲染出来的input框有form-control类属性

widget= widgets.TextInput(attrs={'class':'form-control others'}) # 如果有多个类属性 空格隔开

widget=widgets.PasswordInput(attrs={'class':'form-control others'})

MyRegForm对象的属性和方法

from app01 import views

# 1.给自定义的类传一个字典

obj = views.MyRegForm({'username':'Mark','password':'12','email':'123'})

# 2.判断数据是否全部合法

obj.is_valid() # 只有数据全部符合要求才会是True

# False

# 3.查看符合校验规则的数据

obj.cleaned_data # {'username': 'Mark'}

# 4.查看不符合条件的数据以及不符合的原因是什么

obj.errors # {'password': ['Ensure this value has at least 3 characters (it has 2).'],'email': ['Enter a valid email address.']}

# 5.校验数据的时候 默认情况下类里面所有的字段都必须传值

# 因为校验时是拿着类中的字段取字典中匹对的

obj = views.MyRegForm({'username':'Mark', 'password':'123'})

obj.is_valid() # False

obj.errors # {'email': ['This field is required.']}

# 6.当字典里的数据满足了所有类字段,其余数据并不会看

obj = views.MyRegForm({'username':'Mark', 'password':'1233', 'email':'123@qq.com', 'xxx':'ooo'})

obj.is_valid() # True

注意:

生成MyRegForm对象,里面传字典

is_valid() 当类中的每一个字段都满足了约束,返回值为True

cleaned_data 满足了字段条件的数据会以字典的形式放入这个属性中

errors 不满足字段条件的数据会以字典的形式放入这个属性中,值为列表 套多个 错误信息字符串

前端页面使用的三种方式

forms组件只会帮你渲染获取用户输入(输入,选择,下拉框...)的标签提交按钮需要你自己手动写

方式一

第一种渲染前端页面的方式:封装程度太高了 标签样式及参数不方便调整 可扩展性差(不推荐使用)

{{ MyRegForm对象.as_p }} ——将类中的所有字段生成input框并分别放在p标签中

{{ MyRegForm对象.as_ul }}——将类中的所有字段生成input框并构建无需列表

方式二

扩展性较高 不足之处在于 需要你手写的代码量比较多(不推荐使用)

{{ MyRegForm对象.username.label }}{{ MyRegForm对象.username }}

{{ MyRegForm对象.password.label }}{{ MyRegForm对象.password }}

{{ MyRegForm对象.email.label }}{{ MyRegForm对象.email }}

手动将对象中的属性放入自定义格式中

MyRegForm对象.字段.label 可以获得字段的label值

方式三

代码量和扩展性都很高(推荐使用)

{% for foo in form_obj %}

{{ foo.label }}{{ foo }}

{% endfor %}

PS:前端获得的几个数据

MyRegForm对象.字段.label 可以获得字段的label值

MyRegForm对象.字段 生成对应的input框

MyRegForm对象.字段.errors[0] 获得该字段的错误信息

对MyRegForm对象进行for循环,循环出的是MyRegForm对象.字段

form组件之钩子函数

钩子函数可以对字段做额外的规则校验

当你只需要对某一个字段添加校验时,使用局部钩子

def clean_字段名(self):

例username = self.cleanes_data.get('字段名')

if 规则判断:

self.add_error('字段名','错误信息')

return username

当你需要对多个字段添加校验时,使用全局钩子

def clean(self):

password = self.cleaned_data.get('字段一')

confirm_password = self.cleaned_data.get('字段二')

if not password == confirm_password:

self.add_error('字段名','两次密码不一致')

return self.cleaned_data

使用钩子函数后要有返回值,如果是局部钩子返回钩住的数据即可

如果是全局钩子,要返回 self.cleaned_data

在字段中利用正则添加校验规则

# 1.导入django中的正则

from django.core.validators import RegexValidator

# 2.在字段中添加关键字参数validators

class MyForm(Form):

user = forms.CharField(

validators=[RegexValidator(r'^[0-9]+$', '请输入数字'), RegexValidator(r'^159[0-9]+$', '数字必须以159开头')],)

validators 对应的值是列表,可以放多个正则,RegexValidator(r'正则表达式', '报错信息'),

其他form组件字段

email = forms.EmailField(label='邮箱',error_messages={

'required':'邮箱不能为空',

'invalid':'邮箱格式不正确'

},required=False,widget=widgets.EmailInput(attrs={'class':'form-control'}))

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()

)

总结:添加校验的三种方式

字段

钩子函数

字段中添加正则

自定义分页器

书写一个类,位置不限,一般放在utils文件夹的py文件中

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: 最多显示的页码个数

用法:

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('''

''')

first_page = '

首页' % (1)

page_html_list.append(first_page)

if self.current_page <= 1:

prev_page = '

上一页'

else:

prev_page = '

上一页' % (self.current_page - 1,)

page_html_list.append(prev_page)

for i in range(pager_start, pager_end):

if i == self.current_page:

temp = '

%s' % (i, i,)

else:

temp = '

%s' % (i, i,)

page_html_list.append(temp)

if self.current_page >= self.all_pager:

next_page = '

下一页'

else:

next_page = '

下一页' % (self.current_page + 1,)

page_html_list.append(next_page)

last_page = '

尾页' % (self.all_pager,)

page_html_list.append(last_page)

# 尾部添加标签

page_html_list.append('''

''')

return ''.join(page_html_list)

在使用的地方导入

from app01.utils.mypage import Pagination

使用方法

# 后端

def login(request):

book_queryset = models.Book.objects.all()

current_page = request.GET.get('page',1)

all_count = book_queryset.count()

# 1.实例化产生对象

page_obj = Pagination(current_page=current_page, all_count=all_count)

# 2.对真实数据进行切片操作

page_queryset = book_queryset[page_obj.start:page_obj.end]

return render(request,'login.html',locals())

# 前端

# 获取数据

{% for book_obj in page_queryset %}

{{ book_obj.title }}

{% endfor %}

# 生成分页

{{ page_obj.page_html|safe }}

分页器设计逻辑

获得当前页码

获得展示数据

将对应页码的数据发送到前端

页码一些细节——当前页高亮,显示页数固定,页数随着当前页移动

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值