ModelForm init优化
# utils/modelform.py
from django import forms
class BootStrapModelForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# 循环ModelForm中的所有字段,给每个字段的插件设置
for _, field in self.fields.items():
# 字段中有属性,保留原来的属性,没有属性,才增加
if field.widget.attrs:
field.widget.attrs["class"] = "form-control"
field.widget.attrs["style"] = "width: 300px;"
if "placeholder" in field.widget.attrs:
continue
else:
field.widget.attrs["placeholder"] = field.label
else:
field.widget.attrs = {
"class": "form-control",
"style": "width: 300px;",
"placeholder": field.label
}
# views.py 将目前的三个class类改为继承BootStrapModelForm自定义类并删除三个class的init函数
from blog.utils.modelform import BootStrapModelForm
# ModelForm 方法添加用户
class UserModelForm(BootStrapModelForm):
# xxx = forms.CharField("...") # 自定义数据
# 自定义数据校验覆写
# 例如: 用户名最小三个字符
# name = forms.CharField(min_length=3, label="用户名")
class Meta:
model = Employee
fields = ["name", "password", "age", "account",
"create_time", "gender", "depart"] # 按需引用models字段和自定义字段
widgets = {
"create_time": forms.DateInput(attrs={'class': 'form-control', 'id': 'myDate', "value": "2023-01-01", "style": "width: 300px;", "placeholder": "入职日期"}),
}
class PrettyModelForm(BootStrapModelForm):
# 数据验证 方式一 字段 + 正则
# from django.core.validators import RegexValidator
# mobile = forms.CharField(
# label="手机号",
# validators=[RegexValidator(r'^1\d{10}$', '手机号格式错误')],
# )
class Meta:
model = PrettyNum
fields = ["mobile", "price", "level", "status"]
# fields = "__all__" # 所有字段
# exclude = ['level'] # 排除字段
# 数据验证 方式二 钩子方法
# from django.core.exceptions import ValidationError
def clean_mobile(self):
txt_mobile = self.cleaned_data["mobile"] # 用户传入的数据
pretty_exists = PrettyNum.objects.filter(mobile=txt_mobile).exists()
if pretty_exists:
raise ValidationError("手机号已存在!")
if len(txt_mobile) != 11:
raise ValidationError("格式错误") # 验证不通过
return txt_mobile # 验证通过
class PrettyEditModelForm(BootStrapModelForm):
# mobile = forms.CharField(disabled=True, label="手机号") # 禁止修改手机号
class Meta:
model = PrettyNum
fields = ["mobile", "price", "level", "status"]
# 数据验证 方式二 钩子方法
# from django.core.exceptions import ValidationError
def clean_mobile(self):
# 当前编辑的那一行的ID
# print(self.instance.pk)
txt_mobile = self.cleaned_data["mobile"] # 用户传入的数据
# 编辑时,排除自身以外是否存在一样的手机号
pretty_exists = PrettyNum.objects.filter(
mobile=txt_mobile).exclude(id=self.instance.pk).exists()
if pretty_exists:
raise ValidationError("手机号已存在!")
if len(txt_mobile) != 11:
raise ValidationError("格式错误") # 验证不通过
return txt_mobile # 验证通过
整合form
from blog.models import *
from blog.utils.modelform import BootStrapModelForm
from django.core.validators import RegexValidator
from django.core.exceptions import ValidationError
from django import forms
########################## ModelForm 演示 #############################
# ModelForm 方法添加用户
class UserModelForm(BootStrapModelForm):
# xxx = forms.CharField("...") # 自定义数据
# 自定义数据校验覆写
# 例如: 用户名最小三个字符
# name = forms.CharField(min_length=3, label="用户名")
class Meta:
model = Employee
fields = ["name", "password", "age", "account",
"create_time", "gender", "depart"] # 按需引用models字段和自定义字段
# 逐一控制标签的样式
# widgets = {
# "name": forms.TextInput(attrs={"class": "form-control"}),
# "password": forms.PasswordInput(attrs={"class": "form-control"}),
# "age": forms.TextInput(attrs={"class": "form-control"}),
# }
# 这里让日期可以手动点击鼠标选择,所以单独拎出来,加上日期插件
# widgets = {
# "create_time": forms.DateTimeInput(attrs={'class': 'form-control', 'id': 'myDate', "style": "width: 300px;"}),
# }
widgets = {
"create_time": forms.DateInput(attrs={'class': 'form-control', 'id': 'myDate', "value": "2023-01-01", "style": "width: 300px;", "placeholder": "入职日期"}),
}
# from django.core.validators import RegexValidator
# from django.core.exceptions import ValidationError
# 新增靓号 modelform
# 创建 ModelForm类
class PrettyModelForm(BootStrapModelForm):
# 数据验证 方式一 字段 + 正则
# from django.core.validators import RegexValidator
# mobile = forms.CharField(
# label="手机号",
# validators=[RegexValidator(r'^1\d{10}$', '手机号格式错误')],
# )
class Meta:
model = PrettyNum
fields = ["mobile", "price", "level", "status"]
# fields = "__all__" # 所有字段
# exclude = ['level'] # 排除字段
# 数据验证 方式二 钩子方法
# from django.core.exceptions import ValidationError
def clean_mobile(self):
txt_mobile = self.cleaned_data["mobile"] # 用户传入的数据
pretty_exists = PrettyNum.objects.filter(mobile=txt_mobile).exists()
if pretty_exists:
raise ValidationError("手机号已存在!")
if len(txt_mobile) != 11:
raise ValidationError("格式错误") # 验证不通过
return txt_mobile # 验证通过
# 创建pretty_edit Form类
class PrettyEditModelForm(BootStrapModelForm):
# mobile = forms.CharField(disabled=True, label="手机号") # 禁止修改手机号
class Meta:
model = PrettyNum
fields = ["mobile", "price", "level", "status"]
# 数据验证 方式二 钩子方法
# from django.core.exceptions import ValidationError
def clean_mobile(self):
# 当前编辑的那一行的ID
# print(self.instance.pk)
txt_mobile = self.cleaned_data["mobile"] # 用户传入的数据
# 编辑时,排除自身以外是否存在一样的手机号
pretty_exists = PrettyNum.objects.filter(
mobile=txt_mobile).exclude(id=self.instance.pk).exists()
if pretty_exists:
raise ValidationError("手机号已存在!")
if len(txt_mobile) != 11:
raise ValidationError("格式错误") # 验证不通过
return txt_mobile # 验证通过
优化views.py
新建 views 目录,在views目录新建user.py depart.py pretty.py,按照功能模块分解代码至相应文件
重命名原来的views.py文件为test.py,不然会跟目前的views目录冲突
# depart.py
from typing import Any
from django.shortcuts import render, redirect
from blog.models import Department
from blog.utils.pagination import Pagination
# 员工管理系统-部门管理======================================================================================================
def depart_list(req):
# depart_list = Department.objects.all().order_by("id")
# 通过get传参查询
data_dict = {}
search_data = req.GET.get('title', "") # 有值拿值,没值为空
if search_data:
data_dict["title__contains"] = search_data
# 增加分页
queryset = Department.objects.filter(**data_dict).order_by("id")
page_obj = Pagination(req, queryset)
context = {
"depart_list": page_obj.page_queryset,
"page_string": page_obj.html()
}
return render(req, 'depart_list.html', context)
def depart_add(req):
"""部门添加"""
if req.method == "GET":
return render(req, "depart_add.html")
try:
# 获取用户提交的部门数据
depart_id = req.POST.get("depart_id")
depart_title = req.POST.get("depart_title")
# 保存到数据库
Department.objects.create(dep_id=depart_id, title=depart_title)
# 重定向回部门列表
return redirect("/depart/list/")
except Exception as e:
# print(e)
return render(req, "depart_add.html", {"error_msg": e})
def depart_del(req):
"""部门删除"""
# 获取想要删除的部门ID
nid = req.GET.get("nid")
# 操作数据库删除对应数据
Department.objects.filter(id=nid).delete()
# 重定向回部门列表
return redirect("/depart/list/")
def depart_edit(req, nid):
"""部门编辑"""
# 获取想要编辑的部门ID
if req.method == "GET":
# 查询对应数据
old_title = Department.objects.filter(id=nid).first()
return render(req, "depart_edit.html", {"old_dep_id": old_title.dep_id, "old_title": old_title.title, "nid": nid})
try:
# 获取用户提交的部门数据
depart_id = req.POST.get("depart_id")
depart_title = req.POST.get("depart_title")
# 修改对应数据
Department.objects.filter(id=nid).update(
dep_id=depart_id, title=depart_title)
# 重定向回部门列表
return redirect("/depart/list/")
except Exception as e:
# print(e)
return render(req, "depart_edit.html", {"error_msg": e})
# user.py
from typing import Any
from django.shortcuts import render, redirect
from blog.models import Employee
from blog.models import Department
from blog.utils.pagination import Pagination
from blog.utils.form import UserModelForm
# 员工管理系统-用户管理======================================================================================================
def users_list(req):
# users_list = Employee.objects.all().order_by("id")
# for obj in users_list:
# gender 对应的数据获取
# gender_choices = (
# (1, "男"),
# (2, "女"),
# )
# gender = models.SmallIntegerField(choices=gender_choices,verbose_name="性别")
# print(obj.gender, obj.get_gender_display())
# # depart 外键值获取
# # depart = models.ForeignKey(to="Department", to_field="dep_id", on_delete=models.CASCADE, verbose_name="部门")
# print(obj.depart_id, obj.depart.title)
# # 循环取所有数据
# print(obj.id, obj.name, obj.account, obj.age, obj.create_time.strftime(
# "%Y-%m-%d"), obj.gender, obj.get_gender_display(), obj.depart_id, obj.depart.title)
# html 内写法
# <td>{{ iteam.create_time|date:"Y-m-d" }}</td>
# <td>{{ iteam.get_gender_display }}</td>
# <td>{{ iteam.depart.title }}</td>
# 通过get传参查询
data_dict = {}
search_data = req.GET.get('name', "") # 有值拿值,没值为空
if search_data:
data_dict["name__contains"] = search_data
# 增加分页
queryset = Employee.objects.filter(**data_dict).order_by("id")
# queryset2 = Employee.objects.filter(name__contains="tang").order_by("id")
# print(queryset2)
page_obj = Pagination(req, queryset)
context = {
"users_list": page_obj.page_queryset,
"page_string": page_obj.html()
}
return render(req, 'users_list.html', context)
# 原始方式
def users_add(req):
"""部门添加"""
if req.method == "GET":
# gender_choices = UserInfo.gender_choices
# depart_list = Department.objects.all()
# return render(req, "users_add.html", {"depart_list": depart_list, "gender_choices": gender_choices})
context = {
"gender_choices": Employee.gender_choices,
"depart_list": Department.objects.all()
}
return render(req, "users_add.html", context)
try:
# 获取提交的用户数据
users_name = req.POST.get("users_name")
users_password = req.POST.get("users_password")
users_age = req.POST.get("users_age")
users_account = req.POST.get("users_account")
users_create_time = req.POST.get("users_create_time")
users_gender = req.POST.get("users_gender")
users_depart_id = req.POST.get("users_depart_id")
# 保存到数据库
Employee.objects.create(name=users_name, password=users_password, age=users_age, account=users_account,
create_time=users_create_time, gender=users_gender, depart_id=users_depart_id)
# 重定向回用户列表
return redirect("/users/list/")
except Exception as e:
# print(e)
return render(req, "users_add.html", {"error_msg": e})
def users_add_modelform(req):
"""添加用户(ModelForm版本)"""
if req.method == "GET":
form = UserModelForm()
return render(req, "users_add_modelform.html", {"form": form})
try:
# 用户POST请求提交数据,需要进行数据校验
form = UserModelForm(data=req.POST)
if form.is_valid():
print(form.cleaned_data)
# {'name': 'test', 'password': 'test', 'age': 22, 'account': Decimal('2222'), 'create_time': datetime.date(2023, 1, 5), 'gender': 1, 'depart': <Department: 101:销售>}
# 如果数据合法保存至数据库
# Employee.objects.create(...)
form.save()
return redirect("/users/list/")
# 校验失败(在页面上显示错误信息)
return render(req, "users_add_modelform.html", {"form": form})
except Exception as e:
# print(e)
return render(req, "users_add_modelform.html", {"error_msg": e})
def users_del(req):
"""用户删除"""
# 获取想要删除的用户ID
nid = req.GET.get("nid")
# 操作数据库删除对应数据
Employee.objects.filter(id=nid).delete()
# 重定向回用户列表
return redirect("/users/list/")
def users_edit(req, nid):
"""用户编辑"""
# 根据ID去数据库获取要编辑的那一行数据
row_obj = Employee.objects.filter(id=nid).first()
if req.method == "GET":
form = UserModelForm(instance=row_obj)
return render(req, "users_edit.html", {"form": form, "nid": nid})
try:
# 用户POST请求提交数据,需要进行数据校验
form = UserModelForm(data=req.POST, instance=row_obj)
if form.is_valid():
# print(form.cleaned_data)
# print(form.cleaned_data["create_time"])
# 默认保存的是用户输入的所有数据,如果想要在用户输入以外增加一些值
# form.instance.字段名 = 值
form.save()
return redirect("/users/list/")
# 校验失败(在页面上显示错误信息)
return render(req, "users_edit.html", {"form": form, "nid": nid})
except Exception as e:
# print(e)
return render(req, "users_edit.html", {"nid": nid, "error_msg": e})
# pretty.py
from typing import Any
from django.shortcuts import render, redirect
from blog.models import PrettyNum
from blog.utils.pagination import Pagination
from blog.utils.form import PrettyEditModelForm
from blog.utils.form import PrettyModelForm
# 员工管理系统-靓号管理======================================================================================================
# 靓号展示
def pretty_list(req):
# pretty_list = PrettyNum.objects.all().order_by("id")
# for i in range(99):
# mobile = 15388888790 - i
# price = 88888790 - i
# PrettyNum.objects.create(mobile=mobile, price=price)
# PrettyNum.objects.filter(mobile=mobile, price=price).delete()
# 字典传参写法
# data_dict = {} # 为空则没有条件查询所有数据
# pretty_list = PrettyNum.objects.filter(**data_dict).order_by("id")
# 通过get传参查询
# # http://127.0.0.1:8000/pretty/list/?q=555
data_dict = {}
search_data = req.GET.get('q', "") # 有值拿值,没值为空
if search_data:
data_dict["mobile__contains"] = search_data
# print(req.GET.get)
# 分页函数封装
# from blog.utils.pagination import Pagination
queryset = PrettyNum.objects.filter(**data_dict).order_by("id")
# 初始化封装函数
page_obj = Pagination(req, queryset)
pretty_list = page_obj.page_queryset
# page_string, head_page, end_page = page_obj.html()
page_string = page_obj.html()
context = {
"pretty_list": pretty_list,
"search_data": search_data,
"page_string": page_string,
# "head_page": head_page,
# "end_page": end_page
}
# 符合数据的总条数
# total_count = PrettyNum.objects.filter(**data_dict).order_by("id").count()
# 分页
# page = int(req.GET.get('page', 1))
# page_size = 15
# start = (page - 1) * page_size
# end = page * page_size
# 页码
# from django.utils.safestring import mark_safe
# total_page_count, div= divmod(total_count, page_obj.page_size)
# if div:
# total_page_count += 1
# # 计算显示当前页的前5页,后5页
# plus = 5
# # 如果数据小于等于11页时
# if total_page_count <= 2 * plus +1:
# start_page = 1
# end_page = total_page_count
# else:
# # 如果数据大于11页时
# # 当前页小于等于5时
# if page <= plus:
# start_page = 1
# end_page = 2 * plus + 1
# else:
# # 当前页大于5时
# # 如果大当前页+5 > 总页码
# if page + plus > total_page_count:
# end_page = total_page_count
# start_page = total_page_count - 2 * plus
# else:
# start_page = page - plus
# end_page = page + plus
# page_str_list = []
# # 跳到首页
# head_page = '?page={}'.format(1)
# # 上一页
# if page == 1:
# prev = '<li><a href="/pretty/list/?page=1" aria-label="Previous"><span aria-hidden="true">上一页</span></a></li>'
# else:
# prev = '<li><a href="/pretty/list/?page={}" aria-label="Previous"><span aria-hidden="true">上一页</span></a></li>'.format(page - 1)
# page_str_list.append(prev)
# for i in range(start_page, end_page + 1):
# if i == page:
# ele = '<li class="active"><a href="/pretty/list/?page={}">{}<span class="sr-only">(current)</span></a></li>'.format(i, i)
# else:
# ele = '<li><a href="/pretty/list/?page={}">{}</a></li>'.format(i, i)
# page_str_list.append(ele)
# # 下一页
# if page == total_page_count:
# next = '<li><a href="/pretty/list/?page={}" aria-label="Next"><span aria-hidden="true">下一页</span></a></li>'.format(total_page_count)
# else:
# next = '<li><a href="/pretty/list/?page={}" aria-label="Next"><span aria-hidden="true">下一页</span></a></li>'.format(page + 1)
# page_str_list.append(next)
# # 跳到尾页
# end_page = '?page={}'.format(total_page_count)
# page_string = mark_safe("".join(page_str_list))
# pretty_list = PrettyNum.objects.filter(**data_dict).order_by("id")[page_obj.start:page_obj.end]
# 数据比较筛选
# pretty_list = PrettyNum.objects.filter(id=12).order_by("id") # 等于
# pretty_list = PrettyNum.objects.filter(id__gt=12).order_by("id") # 大于
# pretty_list = PrettyNum.objects.filter(id__gte=12).order_by("id") # 大于等于
# pretty_list = PrettyNum.objects.filter(id__lt=12).order_by("id") # 小于
# pretty_list = PrettyNum.objects.filter(id__lte=12).order_by("id") # 小于等于
# 字符串筛选
# PrettyNum.objects.filter(mobile__startswith="1999") # 筛选出以"1999"开头的
# PrettyNum.objects.filter(mobile__endswith="1999") # 筛选出以"1999"结尾的
# PrettyNum.objects.filter(mobile__contains="1999") # 筛选出包含"1999"的
# print(pretty_list)
return render(req, 'pretty_list.html', context)
# 创建 pretty_add 函数
def pretty_add(req):
if req.method == "GET":
form = PrettyModelForm()
return render(req, "pretty_add.html", {"form": form})
try:
form = PrettyModelForm(data=req.POST)
if form.is_valid():
form.save()
return redirect("/pretty/list/")
return render(req, "pretty_add.html", {"form": form})
except Exception as e:
return render(req, "pretty_add.html", {"error_msg": e})
# 创建 pretty_edit 函数
def pretty_edit(req, nid):
row_obj = PrettyNum.objects.filter(id=nid).first()
# GET
if req.method == "GET":
form = PrettyEditModelForm(instance=row_obj)
return render(req, "pretty_edit.html", {"form": form, "nid": nid})
# POST
form = PrettyEditModelForm(data=req.POST, instance=row_obj)
if form.is_valid():
form.save()
return redirect("/pretty/list/")
return render(req, "pretty_edit.html", {"form": form, "nid": nid})
# pretty_del函数
def pretty_del(req, nid):
PrettyNum.objects.filter(id=nid).delete()
return redirect("/pretty/list/")
urls.py 访问路径修改
from django.contrib import admin
from django.urls import path
from 前端.django.myweb.blog.test import *
from blog.views import depart,user,pretty
from blog import test
urlpatterns = [
path('admin/', admin.site.urls),
path('index_app/', test.index_app),
path('user_list/', test.user_list),
path('', test.tpl),
path('news/', test.news),
path('something/', test.something),
path('login/', test.login),
path('orm/', test.orm),
# 案例 用户列表
path('info_list/', test.info_list),
path('info_add/', test.info_add),
path('info_del/', test.info_del),
# 员工管理系统-部门管理
path('depart/list/', depart.depart_list),
path('depart/add/', depart.depart_add),
path('depart/del/', depart.depart_del),
path('depart/<int:nid>/edit/', depart.depart_edit),
# 员工管理系统-用户管理
path('users/list/', user.users_list),
path('users/add/', user.users_add),
path('users/add_modelform/', user.users_add_modelform),
path('users/del/', user.users_del),
path('users/<int:nid>/edit/', user.users_edit),
# 员工管理系统-靓号管理
path('pretty/list/', pretty.pretty_list),
path('pretty/add/', pretty.pretty_add),
path('pretty/<int:nid>/del/', pretty.pretty_del),
path('pretty/<int:nid>/edit/', pretty.pretty_edit),
]