9.3 员工管理系统-代码优化

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),
]