454 lines
16 KiB
Python
454 lines
16 KiB
Python
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),将将查询到数据对象传递给form(instance=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/')
|