django_project_demo/app/views(含分页源码).py
2024-08-24 03:25:23 +00:00

454 lines
16 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from django.core.validators import RegexValidator # 进行数据校验的正则表达式
from django.core.exceptions import ValidationError # 捕获表单提交的异常错误
from django.shortcuts import render, redirect
from app.models import Department, UserInfo, PrettyNumber
from django import forms # 构建表单模型
from django.utils.safestring import mark_safe # 确保传输的字符串是安全的用于传输拼接分页的html代码
# Create your views here.
def depart_list(request):
"""
部门列表
"""
data_list = Department.objects.all()
return render(request, 'depart_list.html', {'queryset': data_list})
def depart_add(request):
"""
新增部门
"""
if request.method == 'GET':
return render(request, 'depart_add.html')
title = request.POST.get('title')
Department.objects.create(title=title)
return redirect('/depart/list')
def depart_delete(request):
"""
删除部门
"""
nid = request.GET.get('nid')
Department.objects.filter(id=nid).delete()
return redirect('/depart/list')
def depart_edit(request, nid):
"""
编辑部门
nid 用于接收前端传递过来的id,他的名字要和urls.py文件中定义的一样
"""
if request.method == 'GET': # 进入编辑页面
row_object = Department.objects.filter(id=nid).first()
return render(request, 'depart_edit.html', {'row_object': row_object})
# 保存修改POST提交
title = request.POST.get('title')
Department.objects.filter(id=nid).update(title=title)
return redirect('/depart/list')
def user_list(request):
"""
用户列表
"""
data_list = UserInfo.objects.all()
return render(request, 'user_list.html', {'queryset': data_list})
def user_add(request):
"""
添加用户 (原始实现方式)
缺点:
1.要重复前端form表单
2.用户提交数据未校验
3.前端输入错误没有提示
4.关联的数据要手动获取,前端要循环渲染
"""
if request.method == 'GET':
content = {
'gender': UserInfo.gender_choices,
'depart': Department.objects.all()
}
return render(request, 'user_add.html', content)
name = request.POST.get('name')
password = request.POST.get('password')
age = request.POST.get('age')
account = request.POST.get('account')
create_time = request.POST.get('create_time')
depart_id = request.POST.get('depart')
gender = request.POST.get('gender')
UserInfo.objects.create(name=name, password=password, age=age,
account=account, create_time=create_time,
depart_id=depart_id, gender=gender)
return redirect('/user/list')
class UserModelForm(forms.ModelForm):
"""
用户类表单模型
作用:用于定义渲染到前端的数据,设置校验规则等
用法:
用ModelForm来操作表记录
1.基本用法首先从django.forms导入ModelForm
2.编写一个自己的类继承ModelForm
3.在新类里设置元类Meta
4.在Meta中设置model属性为你要关联的ORM模型这里是UserInfo
5.在Meta中设置fields属性为你要在表单中使用的字段列表
6.列表里的值应该是ORM模型model中的字段名。
"""
# 重新定义name字段的属性和校验规则
name = forms.CharField(min_length=2, label='姓名')
class Meta:
model = UserInfo # 指定需要显示的表名在models.py中定义
# 指定要操作的字段名,是一个列表
fields = ['name', 'age', 'gender', 'depart', 'create_time', 'account']
# 给表单控件逐个添加属性
# widgets = {
# 'name': forms.TextInput(attrs={'class': 'form-control'}),
# 'password': forms.PasswordInput(attrs={'class': 'form-control'}),
# 'create_time': forms.DateInput(attrs={'class': 'form-control'}),
# }
# 给所有表单控件添加属性
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
for name, field in self.fields.items():
field.widget.attrs = {"class": "form-control"}
class PrettyNumberForm(forms.ModelForm):
"""
靓号类表单模型
具体使用注解见UserModelForm类
"""
# 重新定义mobile字段的属性和校验规则 方式1
mobile = forms.CharField(
min_length=11, # 最小长度
label='号码',
# 通过正则进行数据校验
validators=[RegexValidator(r'^1[3-9]\d{9}$', '号码错误,长度不能超过11位')],
)
class Meta:
model = PrettyNumber # 指定需要显示的表名在models.py中定义
# 指定要操作的字段名,是一个列表
# fields = ['mobile', 'price', 'level', 'status']
fields = '__all__' # 渲染所有字段
# exclude = ['level'] # 排除某个字段
# 给所有表单控件添加属性
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
for name, field in self.fields.items():
field.widget.attrs = {"class": "form-control"}
# 对字段进行一些数据校验或操作 方式2
# 名称必须是clean_字段名
# 也称为钩子方法,更灵活,比如手机号是否已经存在...
def clean_mobile(self):
txt_value = self.cleaned_data['mobile'] # 获取到用户输入的字段值
num_exist = PrettyNumber.objects.filter(mobile=txt_value).exists()
if num_exist:
raise ValidationError("号码已经存在")
return txt_value
class PrettyNumberEditForm(forms.ModelForm):
"""
靓号编辑类表单模型
具体使用注解见UserModelForm类
"""
# 重新定义mobile字段的属性和校验规则 方式1
mobile = forms.CharField(
label='号码11',
disabled=True,
)
class Meta:
model = PrettyNumber # 指定需要显示的表名在models.py中定义
# 指定要操作的字段名,是一个列表
# fields = ['mobile', 'price', 'level', 'status']
fields = '__all__' # 渲染所有字段
# 给所有表单控件添加属性
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
for name, field in self.fields.items():
field.widget.attrs = {"class": "form-control"}
# 对字段进行一些数据校验或操作 方式2
# 名称必须是clean_字段名
# 也称为钩子方法,更灵活,比如手机号是否已经存在...
def clean_mobile(self):
txt_value = self.cleaned_data['mobile'] # 获取到用户输入的字段值
# instance是编辑时传入的值pk是id主键
nid = self.instance.id
# print(self.instance.mobile)
# 修改时,要排除当前号码以外的其他数据
# 也就是 where mobile=18995009009 and id!=2
num_exist = PrettyNumber.objects.filter(mobile=txt_value).exclude(id=nid)
if num_exist:
raise ValidationError("号码已经存在")
return txt_value
def user_add_modelform(request):
"""
添加用户通过Django ModelForm组件实现 最简便)
"""
if request.method == 'GET':
form = UserModelForm() # 实例化类
return render(request, 'user_add_modelform.html', {'form': form})
# POST请求
form = UserModelForm(data=request.POST) # 拿到所有提交过来的数据
if form.is_valid(): # 数据校验
# 如果你想对数据表中的字段另外再传递值来保存,就用
# form.instance.字段名 = '值'
form.instance.password = '0000' # 默认密码是0000
form.save() # 向 model = UserInfo 定义的表保存数据
return redirect('/user/list/')
else:
# form中带了POST过来的请求
return render(request, 'user_add_modelform.html', {'form': form})
def user_edit_modelform(request, nid):
"""
用户信息修改
nid 用于接收前端传递过来的id,他的名字要和urls.py文件中定义的一样
"""
# 1.先查询到该条记录
# 2.拿到POST请求过来的数据data=request.POST将将查询到数据对象传递给forminstance=row_data
row_data = UserInfo.objects.filter(id=nid).first()
if request.method == 'GET':
form = UserModelForm(instance=row_data) # 将查询到的对象传递给form
return render(request, 'user_edit_modelform.html', {'form': form})
# POST请求
form = UserModelForm(data=request.POST, instance=row_data) # 拿到所有提交过来的数据
if form.is_valid(): # 数据校验
form.save() # 向 model = UserInfo 定义的表保存数据
return redirect('/user/list/')
else:
# form中带了POST过来的请求
return render(request, 'user_edit_modelform.html', {'form': form})
def user_delete_modelform(request, nid):
"""
用户信息删除
nid 用于接收前端传递过来的id,他的名字要和urls.py文件中定义的一样
"""
UserInfo.objects.filter(id=nid).delete()
return redirect('/user/list/')
def pn_list(request):
"""
靓号列表
"""
# 第一次显示的时候查询条件也就是data_dict为空所以查询所有数据
data_dict = {}
# search_data = ""
search_data = request.GET.get('searchMobile', '')
# 如果提交了查询的号码,则把号码拿到后添加到字典中,同时也把该数据再返回给前端,让搜索框不丢失数据
# if request.method == 'POST':
# search_data = request.POST.get('searchMobile')
# data_dict['mobile__contains'] = search_data
# # print(value)
if search_data:
data_dict['mobile__contains'] = search_data
"""
分页实现,准备数据阶段
PAGE_SIZE 每页显示记录数
star_page_data 开始记录数
end_page_data 结束记录数
total_count_data 总记录数
total_count_page 总页数
"""
# ########## 准备数据阶段 ##########
PAGE_SIZE = 10 # 每页10条数据
page = int(request.GET.get('indexPage', 1)) # 当前页,默认第1页,如果是跳转的就读indexPage输入框内的值
star_page_data = (page - 1) * PAGE_SIZE # 开始数据
end_page_data = page * PAGE_SIZE # 结束数据
# 统计共有多少条数据
total_count_data = PrettyNumber.objects.filter(**data_dict).order_by('-level').count()
# ########## 分页数据准备结束 ##########
"""
生成分页导航条
计算出当前页前5页和后5页的页码
PLUS_NAV 前后显示几页
star_page 起始页
end_page 结束页
total_count_page 总页数
page_nav 导航条的html代码
"""
# 计算总页数 方法:通过总记录数和每页显示数相除
# divmod函数是python自带函数计算两数相除同时获得商和余数例如 divmod(91,10) 结果等于 {9,1}
# total_count_page总页数 mod就是余数
total_count_page, mod = divmod(total_count_data, PAGE_SIZE)
if mod:
total_count_page += 1 # 如果有余数总页数+1
# 计算导航栏页码数和显示方式(要考虑翻页时的极值)
# 效果是前5页和后5页
PLUS_NAV = 5
# 当数据量少比如只有100条数据以内则展示全部导航条
if total_count_page <= PLUS_NAV * 2:
star_page = 1
end_page = total_count_page
else: # 大于100条数据时 显示前后5条数据
# 如果当前页小于5条极植
if page <= PLUS_NAV:
star_page = 1
end_page = PLUS_NAV * 2
else:
# 当前是每后一页时(极植)
if (page + PLUS_NAV) >= total_count_page:
star_page = total_count_page - PLUS_NAV * 2 # 显示前10页导航
end_page = total_count_page
else:
star_page = page - PLUS_NAV
end_page = page + PLUS_NAV
# 生成分页导航条的html代码并传递给前端
page_list = []
# 首页
# prev = '<li><a href="?page=1">首页</a></li>'
prev = '<li><a href="?indexPage=1" aria-label="Previous"><span aria-hidden="true">«</span></a></li>'
page_list.append(prev)
# 上一页
if page > 1:
prev = f'<li><a href="?indexPage={page - 1}">上一页</a></li>'
page_list.append(prev)
for i in range(star_page, end_page + 1): # range前取后不取所以+1
if i == page:
ele = f'<li class="active"><a href="?indexPage={i}">{i}</a></li>' # 给当前页加效果
else:
ele = f'<li><a href="?indexPage={i}">{i}</a></li>'
page_list.append(ele)
# 下一页
if page < total_count_page:
prev = f'<li><a href="?indexPage={page + 1}">下一页</a></li>'
page_list.append(prev)
# 尾页
# prev = f'<li><a href="?page={total_count_page}">尾页</a></li>'
prev = f'<li><a href="?indexPage={total_count_page}" aria-label="Previous"><span aria-hidden="true">»</span></a></li>'
page_list.append(prev)
# 构建跳转html
page_nav_search = """
<li>
<form method="get" style="float: left;margin-left: -1px">
<input style="width: 100px;position: relative;float: left;display: inline-block;border-radius: 0" type="text" name="indexPage" class="form-control" placeholder="页码..">
<button style="border-radius: 0;" class="btn btn-default" type="submit">跳转</button>
</form>
</li>
"""
page_list.append(page_nav_search)
page_nav = ''.join(page_list)
# 因为page_nav是一个html字符串所以在传递到前端时要转换为安全的字符串
page_nav = mark_safe(page_nav)
"""分页实现结束"""
# 字典格式: data_dict = {mobile__contains: '9999'}
# **data_dict传入字典必须以**打头
# order_by('-level') 倒序排列
# [0:10] 取前10条数据
data_list = PrettyNumber.objects.filter(**data_dict).order_by('-level')[star_page_data:end_page_data]
return render(request, 'PrettyNumber_list.html',
{'queryset': data_list, 'search_data': search_data, 'page_nav': page_nav})
def pn_add(request):
"""
增加靓号
"""
if request.method == 'GET':
form = PrettyNumberForm() # 实例化表单模型类
return render(request, 'PrettyNumber_add_modelform.html', {'form': form})
# POST请求
form = PrettyNumberForm(data=request.POST) # 拿到所有提交过来的数据
if form.is_valid(): # 数据校验
# 如果你想对数据表中的字段另外再传递值来保存,就用
# form.instance.字段名 = '值'
# form.instance.password = '0000' # 默认密码是0000
form.save() # 向 model = PrettyNumber 定义的表保存数据
return redirect('/PrettyNumber/list/')
else:
# form中带了POST过来的请求
return render(request, 'PrettyNumber_add_modelform.html', {'form': form})
def pn_edit(request, nid):
"""
靓号编辑
"""
row_data = PrettyNumber.objects.filter(id=nid).first()
if request.method == 'GET':
form = PrettyNumberEditForm(instance=row_data) # 将查询到的对象传递给form
return render(request, 'PrettyNumber_edit_modelform.html', {'form': form})
# POST请求
form = PrettyNumberEditForm(data=request.POST, instance=row_data) # 拿到所有提交过来的数据
if form.is_valid(): # 数据校验
form.save() # 向 model = UserInfo 定义的表保存数据
return redirect('/PrettyNumber/list/')
else:
# form中带了POST过来的请求
return render(request, 'PrettyNumber_edit_modelform.html', {'form': form})
def pn_delete(request, nid):
"""
靓号删除
"""
PrettyNumber.objects.filter(id=nid).delete()
return redirect('/PrettyNumber/list/')