【Django 网页Web开发】14. 实战项目:一些面向对象的代码结构优化(07)(保姆级图文)


欢迎关注 『Django 网页Web开发』 系列,持续更新中
欢迎关注 『Django 网页Web开发』 系列,持续更新中

1. bootstrap类

1.1 初始化时给ModelForm组件添加bootstrap样式的优化

  • 原先的代码,无论如何都是把原来组件的属性替换为了我们规定的属性
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # 循环找到所有的插件,添加了class="form-control"
        for name, field in self.fields.items():
            # if name == "password":
            #     continue
            field.widget.attrs = {"class": "form-control", "placeholder": field.label}
  • 优化后的代码,在原有属性的基础上添加我们新增的属性
class BootStrapModelForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # 循环ModelForm中的所有字段,给每个字段的插件设置
        for name, field in self.fields.items():
            # 字段中有属性,保留原来的属性,没有属性,才增加。
            if field.widget.attrs:
                field.widget.attrs["class"] = "form-control"
                field.widget.attrs["placeholder"] = field.label
            else:
                field.widget.attrs = {
                    "class": "form-control",
                    "placeholder": field.label
                }
  • 突然发现view.py已经有400+行的长度(虽然有不少是注释)
  • 但是我们还发现有不少冗余代码,我们在每个表的ModelForm中都定义了下面这个相同的方法,能不能把这个常用的方法也像我们分页组件一样集成封装到类中呢?

1.2 封装bootstrap类

在这里插入图片描述

  • bootstrap.py内容
from django import forms


class BootStrapModelForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # 循环ModelForm中的所有字段,给每个字段的插件设置
        for name, field in self.fields.items():
            # 字段中有属性,保留原来的属性,没有属性,才增加。
            if field.widget.attrs:
                field.widget.attrs["class"] = "form-control"
                field.widget.attrs["placeholder"] = field.label
            else:
                field.widget.attrs = {
                    "class": "form-control",
                    "placeholder": field.label
                }

1.3 让其他调用modelForm的类继承我们的bootstrap类

  • 先把forms.ModelForm替换为BootStrapModelForm
    在这里插入图片描述
  • 然后导入我们写好的bootstrap类
    在这里插入图片描述
  • 删除掉原来我们在各个类中写好的 def __init__(self, *args, **kwargs):
  • 可以看到我们各个组件的样式仍然保留,并且以后我们新建moudleForm类只需继承bootstrap类即可实现对于所有组件样式的添加,方便快捷!

2. form类

把所有的表单类集中到一个类,放在一起写,从view.py中分离出来方便后期的管理维护。

2.1 封装form类

在这里插入图片描述
在这里插入图片描述

from app01 import models
from django.core.validators import RegexValidator
from django.core.exceptions import ValidationError
from django import forms
from app01.utils.bootstrap import BootStrapModelForm

# 新建一个StudyModelForm类
class StudyModelForm(BootStrapModelForm):
    # 一般错误检查是非空,如果要有其他检查比如最小长度3,需要像下面这样另外写(回到了form的那种)
    username = forms.CharField(min_length=3, label="用户名")

    # 创建子类,选择数据字段,给不同字段设置样式
    class Meta:
        model = models.TestForm  # 选择数据表,model表示读取数据表的指定字段
        # models = models.TestForm #选择数据表,models表示默认读取数据表的所有字段
        fields = ["username", "password"]  # 选择数据表的字段
        # widgets = {
        #     "username": forms.TextInput(attrs={"class": "form-control"}),
        #     "password": forms.PasswordInput(attrs={"class": "form-control"}),
        # }


class UserModelForm(BootStrapModelForm):
    name = forms.CharField(min_length=3, label="用户名")
    password = forms.CharField(min_length=6, label="密码")

    class Meta:
        model = models.UserInfo
        fields = ["name", "password", "age", 'account', 'create_time', "gender", "depart"]
        # widgets = {
        #     "name": forms.TextInput(attrs={"class": "form-control"}),
        #     "password": forms.PasswordInput(attrs={"class": "form-control"}),
        #     "age": forms.TextInput(attrs={"class": "form-control"}),
        # }


class PrettyModelForm(BootStrapModelForm):
    # # 数据校验:方式1 字段+正则
    # mobile = forms.CharField(
    #     label="手机号",
    #     #通过正则的方式直接判断
    #     validators=[RegexValidator(r'^1[3-9]\d{9}$', '字段+正则手机号格式错误'), ],#正则匹配首位数字1,第二位数字3-9,接下来9位数字
    # )

    # 数据校验:方式2 钩子方法
    def clean_mobile(self):
        # 当前编辑的哪一行的ID
        print(self.instance.pk)
        txt_mobile = self.cleaned_data["mobile"]  # 拿到了手机号码数据可以通过if等逻辑进行判断
        # if len(txt_mobile)!=11:
        #     raise ValidationError("钩子方法:手机号长度不对劲")
        exists = models.PrettyNum.objects.exclude(id=self.instance.pk).filter(mobile=txt_mobile).exists()
        if exists:
            raise ValidationError("钩子方法:手机号已存在")

        # 验证通过,用户输入的值返回
        return txt_mobile

    class Meta:
        model = models.PrettyNum
        fields = ["mobile", "price", "level", "status"]  # 选择展示的字段
        # fields="__all__"#显示所有字段
        # exclude=["id"]#不显示id字段

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # 循环找到所有的插件,添加了class="form-control"
        for name, field in self.fields.items():
            # if name == "password":
            #     continue
            field.widget.attrs = {"class": "form-control", "placeholder": field.label}

class PrettyEditModelForm(BootStrapModelForm):
    mobile = forms.CharField(disabled=True, label="手机号")  # 让手机号可以显示,但是不能修改

    class Meta:
        model = models.PrettyNum
        fields = ['mobile', 'price', 'level', 'status']


    # 数据校验:方式2 钩子方法
    def clean_mobile(self):

        print(self.instance.pk)  # 当前编辑的哪一行的ID
        txt_mobile = self.cleaned_data["mobile"]  # 拿到了手机号码数据可以通过if等逻辑进行判断
        # if len(txt_mobile)!=11:
        #     raise ValidationError("钩子方法:手机号长度不对劲")

        exists = models.PrettyNum.objects.exclude(id=self.instance.pk).filter(mobile=txt_mobile).exists()
        if exists:
            raise ValidationError("钩子方法:手机号已存在")

        # 验证通过,用户输入的值返回
        return txt_mobile

2.2 让view.py调用form.py中的类

from app01.utils.form import StudyModelForm,UserModelForm,PrettyModelForm,PrettyEditModelForm

3. view.py按功能拆分

3.1 view拆分结构

按照功能分为三类
在这里插入图片描述

3.2 把对应功能的代码迁移到对应py文件

注意移动后导包,把所需要的各种包导入好。

3.2.1 depart.py

from django.shortcuts import redirect, render
from app01 import models


def depart_list(request):
    """ 部门列表 """

    # 去数据库中获取所有的部门列表
    #  [对象,对象,对象]
    queryset = models.Department.objects.all()

    return render(request, 'depart_list.html', {'queryset': queryset})


def depart_add(request):
    """ 添加部门 """
    if request.method == "GET":
        return render(request, 'depart_add.html')

    # 获取用户POST提交过来的数据(title输入为空)
    title = request.POST.get("title")

    # 保存到数据库
    models.Department.objects.create(title=title)

    # 重定向回部门列表
    return redirect("/depart/list/")


def depart_delete(request):
    """ 删除部门 """
    # 获取ID http://127.0.0.1:8000/depart/delete/?nid=1
    nid = request.GET.get('nid')

    # 删除
    models.Department.objects.filter(id=nid).delete()

    # 重定向回部门列表
    return redirect("/depart/list/")


def depart_edit(request, nid):
    """ 修改部门 """
    if request.method == "GET":
        # 根据nid,获取他的数据 [obj,]
        row_object = models.Department.objects.filter(id=nid).first()
        return render(request, 'depart_edit.html', {"row_object": row_object})

    # 获取用户提交的标题
    title = request.POST.get("title")

    # 根据ID找到数据库中的数据并进行更新
    # models.Department.objects.filter(id=nid).update(title=title,其他=123)
    models.Department.objects.filter(id=nid).update(title=title)

    # 重定向回部门列表
    return redirect("/depart/list/")

3.2.2 pretty.py

from django.shortcuts import redirect, render
from app01 import models
from app01.utils.form import PrettyModelForm, PrettyEditModelForm
from app01.utils.pagination import Pagination


def pretty_list(request):
    """ 靓号列表 """

    ## 随机创建若干数据,写好后f5刷新一下列表生效后注释掉这些代码
    # for i in range(300):
    #     models.PrettyNum.objects.create(mobile=random.randint(13000000000,19000000000),price=random.randint(1,1000),level=random.randint(1,4),status=random.randint(1,2))

    # import copy
    # query_dict=copy.deepcopy(request.GET)#http://127.0.0.1:8000/pretty/list/?q=1&csdn=2023
    # print(query_dict.urlencode())#q=1&csdn=2023
    # query_dict.mutable=True#不修改这个参数就会报错提示无法修改
    # query_dict.setlist('page',[11])#q=1&csdn=2023&page=11 在原来的基础上增加了&page=11
    # print(query_dict.urlencode())#讲url打印出来


    data_dict = {}
    search_data = request.GET.get("q","")
    if search_data:  # 如果传来的参数非空就搜索,反之显示所有数据
        data_dict["mobile__contains"] = search_data  # 是否包含指定数据

    queryset = models.PrettyNum.objects.filter(**data_dict).order_by("-level")  # -level表示按照level降序排列显示

    page_object = Pagination(request, queryset)
    context = {
        "search_data": search_data,
        "queryset": page_object.page_queryset,  # 分完页的数据
        "page_string": page_object.html()  # 页码
    }
    return render(request, 'pretty_list.html', context)




from django.core.exceptions import ValidationError  # 导入Django异常模块



def pretty_add(request):
    """ 添加靓号 """
    if request.method == "GET":
        form = PrettyModelForm()
        return render(request, 'pretty_add.html', {"form": form})  # 通过render将对象传入到HTML中。
    form = PrettyModelForm(data=request.POST)
    if form.is_valid():  # 数据校验
        form.save()  # 保存到数据库
        return redirect('/pretty/list/')  # 跳转回靓号列表
    return render(request, 'pretty_add.html', {"form": form})




def pretty_edit(request, nid):
    """ 编辑靓号 """
    row_object = models.PrettyNum.objects.filter(id=nid).first()

    if request.method == "GET":
        form = PrettyEditModelForm(instance=row_object)
        return render(request, 'pretty_edit.html', {"form": form})

    form = PrettyEditModelForm(data=request.POST, instance=row_object)
    if form.is_valid():
        form.save()
        return redirect('/pretty/list/')

    return render(request, 'pretty_edit.html', {"form": form})


def pretty_delete(request, nid):
    models.PrettyNum.objects.filter(id=nid).delete()
    return redirect('/pretty/list/')

3.2.3 user.py

from django.shortcuts import redirect, render
from app01 import models
from app01.utils.form import UserModelForm
from app01.utils.pagination import Pagination

def user_list(request):
    """ 用户管理 """
    ## 随机创建若干数据,写好后f5刷新一下列表生效后注释掉这些代码
    # for i in range(300):
    #     models.UserInfo.objects.create(name="张龙分身{}".format(i),password="123456",age=1,account=1,gender=1,create_time="2023-03-15 10:00:17.000000", depart_id=1)

    # 获取所有用户列表 [obj,obj,obj]
    queryset = models.UserInfo.objects.all()

    page_object = Pagination(request, queryset, page_size=5)
    context = {
        "queryset": page_object.page_queryset,
        "page_string": page_object.html(),
    }
    return render(request, 'user_list.html', context)

    """
    # 用Python的语法获取数据
    for obj in queryset:
        print(obj.id, obj.name, obj.account, obj.create_time.strftime("%Y-%m-%d"), obj.gender, obj.get_gender_display(), obj.depart_id, obj.depart.title)
        # print(obj.name, obj.depart_id)
        # obj.depart_id  # 获取数据库中存储的那个字段值
        # obj.depart.title  # 根据id自动去关联的表中获取哪一行数据depart对象。
    """


def user_add(request):
    """ 添加用户(原始方式) """

    if request.method == "GET":
        context = {
            'gender_choices': models.UserInfo.gender_choices,
            "depart_list": models.Department.objects.all()
        }
        return render(request, 'user_add.html', context)

    # 获取用户提交的数据
    user = request.POST.get('user')
    pwd = request.POST.get('pwd')
    age = request.POST.get('age')
    account = request.POST.get('ac')
    ctime = request.POST.get('ctime')
    gender = request.POST.get('gd')
    depart_id = request.POST.get('dp')

    # 添加到数据库中
    models.UserInfo.objects.create(name=user, password=pwd, age=age,
                                   account=account, create_time=ctime,
                                   gender=gender, depart_id=depart_id)

    # 返回到用户列表页面
    return redirect("/user/list/")


# ################################# ModelForm 示例 #################################
from django import forms


def user_model_form_add(request):
    """ 添加用户(ModelForm版本)"""
    if request.method == "GET":
        form = UserModelForm()
        return render(request, 'user_model_form_add.html', {"form": form})

    # 用户POST提交数据,数据校验。
    form = UserModelForm(data=request.POST)
    if form.is_valid():
        # 如果数据合法,保存到数据库
        # {'name': '123', 'password': '123', 'age': 11, 'account': Decimal('0'), 'create_time': datetime.datetime(2011, 11, 11, 0, 0, tzinfo=<UTC>), 'gender': 1, 'depart': <Department: IT运维部门>}
        # print(form.cleaned_data)
        # models.UserInfo.objects.create(..)
        form.save()
        return redirect('/user/list/')

    # 校验失败(在页面上显示错误信息)
    return render(request, 'user_model_form_add.html', {"form": form})


def user_edit(request, nid):
    """ 编辑用户 """
    row_object = models.UserInfo.objects.filter(id=nid).first()  # 获取指定用户的那一行数据

    if request.method == "GET":
        # 根据ID去数据库获取要编辑的那一行数据(对象)
        form = UserModelForm(instance=row_object)
        # instance 数据表的某一行,ModelForm会自动把这一行数据填充到表单中,也就是修改数据时,一开始的输入框中填写好了原来修改前的值
        return render(request, 'user_edit.html', {'form': form})

    form = UserModelForm(data=request.POST, instance=row_object)
    if form.is_valid():  # 如果是合法的数据准备保存进数据库
        # 默认保存的是用户输入的所有数据,如果想要再用户输入以外增加一点值
        # form.instance.字段名 = 值
        form.save()
        return redirect('/user/list/')
    return render(request, 'user_edit.html', {"form": form})  # 如果数据不合法


def user_delete(request, nid):
    models.UserInfo.objects.filter(id=nid).first().delete()  # 一行delete,这个first可加可不加,看你的id是否唯一
    return redirect('/user/list/')

3.3 修改url.py中与view对应的路径

核心在于导入三个新类,然后把原来的view替换为对应的新类类名,然后把view删除掉。400+行的view按照功能化整为零。

from app01.views import depart
from app01.views import pretty
from app01.views import user
from django.urls import path

from app01 import views
from app01.views import depart
from app01.views import pretty
from app01.views import user

urlpatterns = [
    path('depart/list/',depart. depart_list),  # 部门列表
    path('depart/add/', depart.depart_add),  # 部门添加
    path('depart/delete/', depart.depart_delete),  # 部门删除
    path('depart/<int:nid>/edit/', depart.depart_edit),  # 部门编辑

    path('user/list/', user.user_list),  # 用户列表
    path('user/add/', user.user_add),  # 用户添加

    path('user/model/form/add/', user.user_model_form_add),  # 添加用户(ModelForm版本)
    path('user/<int:nid>/edit/', user.user_edit),
    path('user/<int:nid>/delete/', user.user_delete),

    # 靓号管理
    path('pretty/list/', pretty.pretty_list),
    path('pretty/add/', pretty.pretty_add),
    path('pretty/<int:nid>/edit/', pretty.pretty_edit),
    path('pretty/<int:nid>/delete/', pretty.pretty_delete),

]


总结

大家喜欢的话,给个👍,点个关注!给大家分享更多有趣好玩的Python 网页Web开发知识!

版权声明:

发现你走远了@mzh原创作品,转载必须标注原文链接

Copyright 2023 mzh

Crated:2023-3-1

欢迎关注 『Django 网页Web开发』 系列,持续更新中
欢迎关注 『Django 网页Web开发』 系列,持续更新中
『01. 安装配置Django』
『02. 创建并运行一个Django项目』
『03. 初识Django』
『04. 请求和响应,网页跳转重定向,实战简易表单模拟登陆』
『05. 数据库操作,实战用户管理』
『06. 报错:You have 26 unapplied migration(s). Your project may not work properly until you apply the migra』
『07. 模板语法』
『08. 实战项目:部门和员工管理系统(01)』
『09. 实战项目:员工编辑删除功能与靓号管理(02)』
『10. 实战项目:靓号搜索功能(03)』
『11. 实战项目:分页与页码跳转功能(04)』
『12. 实战项目:分页组件的封装 面向接口编程(05)』
『13. 实战项目:添加用户时的时间选择组件(06)』
『14. 实战项目:一些面向对象的代码结构优化(07)』
『15. 实战项目:管理员增删改查,md5密码和密码重置(08)』
『16. 实战项目:BootStrap类的进一步优化(09)』
『17. 实战项目:login业务涉及cookie、session、中间件(10)』
『18. 实战项目:登录时的验证码(11)』
『19. 实战项目:初识Ajax请求(12)』
『20. 实战项目:Ajax实战之订单管理与弹出对话框(13)』
『21. 实战项目:echart数据图表(14)』
『22. 实战项目:简单的文件上传(15)』
『23. 实战项目:Excel和form和moudleForm的文件上传(16)』
【更多内容敬请期待】


内容概要:本文系统梳理了多个科研领域的前沿研究与技术实现,重点涵盖FDTD方法中的完美匹配层(PML)研究,以及Matlab/Simulink在电磁、电力、控制、通信、信号处理、图像处理、路径规划、能源系统优化等领域的仿真与算法实现。文中列举了大量基于Matlab和Python的科研案例,如风电功率预测、负荷预测、无人机三维路径规划、电池系统故障诊断、雷达模拟、通信编码、微电网优化调度等,强调结合智能优化算法(如粒子群、遗传算法、深度学习等)提升系统性能。同时,提供了丰富的代码资源与仿真模型,涵盖永磁同步电机控制、逆变器设计、多智能体任务配、虚拟电厂调度等复杂系统,助力科研人员快速开展复现实验与创新研究。; 适合人群:具备一定编程基础,熟悉Matlab/Python工具,从事电气工程、自动化、通信、人工智能、新能源、控制科学等相关领域研究的研发人员及研究生。; 使用场景及目标:① 学习实现FDTD仿真中的PML边界条件以有效抑制数值反射;② 掌握Matlab/Simulink在多物理场建模、控制系统设计与优化算法中的综合应用;③ 借助提供的代码资源完成科研复现、课程设计、竞赛项目或工程原型开发; 阅读建议:此资源以科研实战为导向,不仅提供理论方法,更强调代码实现与仿真验证。建议读者结合自身研究方向,按目录顺序查阅相关模块,下载配套代码进行调试与二次开发,以达到学以致用、融会贯通的目的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

发现你走远了

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值