【Django项目开发】功能菜单模型类设计、视图类设计要点(一)

news2024/10/7 15:29:43

在这里插入图片描述


一、抽象模型类设计

1、抽象模型类设计的作用:

1、定义所有模型类的公共属性,当其他的模型类继承该抽象模型类时,就具备了模型类中的属性了;在项目开发中,减少代码的编写
2、抽象模型类中经常定义的字段包括:id、创建时间、更新时间
3、class Meta类中需要定义abstract=True:表示抽象模型类,不需要映射表
4、模型类需要继承models.Model

2、auto_now_add和auto_now的区别:

auto_now_add:表示创建时间,只在创建该条数据的时候会生成当前时间保存在数据库中,之后任何操作不会改变时间
auto_now:表示更新时间,数据的更新、修改,时间会变化

from django.db import models

class BaseModel(models.Model):
    '''
    所有模型的抽象类,定义所有表共有的属性
    '''
    create_time=models.DateTimeField(auto_now_add=True,
                                     verbose_name='创建时间',
                                     help_text='创建时间',
                                     )

    update_time=models.DateTimeField(auto_now=True,
                                     help_text='更新时间',
                                     verbose_name='更新时间')

    class Meta:
        abstract=True       #todo 表示抽象模型类,不需要映射表

二、功能菜单模型类的设计

功能菜单模型类需要继承模型类BaseModel

1、菜单都需要那些字段

1、排序数字:例如下图,菜单的顺序由排序数字决定,数字小的在最上面展示
在这里插入图片描述
2、菜单名称
3、url:父级菜单没有url,点击父级菜单展示显示子菜单;子菜单才有url
4、delete_flag:当对菜单进行删除操作时,不会真正的把菜单进行删除,默认为0,如果是1当前记录删除
5、parent:外键字段

2、一些注意点

1、当模型类自己与自己关联时:关联字段设置为"self"
2、related_name=‘children’:设置反向关联的属性;
当父表获取子表数据的时候时:父表模型对象.children
子表获取父表数据的时候时:子表模型对象.parent
3、on_delete=models.CASCADE:表示当父表的数据删除时,子表的数据怎么变化;models.CASCADE:表示父表中关联的子表数据也将删除
4、CharField中必须指定max_length的属性

3、blank=True和null=True的区别

blank=True:表示提交表单的时候可以为空
null=True:表示数据库中该字段可以为空

from django.db import models
from erp_project.utils.base_model import BaseModel
from django.contrib.auth.models import AbstractUser


# Create your models here.

class MenuModel(BaseModel):
    '''功能菜单的模型类'''
    number = models.IntegerField(help_text='排序数字',
                                 verbose_name='排序数字',
                                 blank=True,
                                 null=True)
    url = models.CharField(help_text='菜单访问的url',
                           verbose_name='菜单访问的url',
                           max_length=256,
                           blank=True,
                           null=True)
    name = models.CharField(help_text='菜单名字',
                            verbose_name='菜单名字',
                            unique=True,
                            max_length=50)
    # 不会真正的把数据库中的数据删除,默认为0,如果是1当前记录删除
    delete_flag = models.CharField(help_text='删除标记',
                                   verbose_name='删除标记',
                                   max_length=1,
                                   default='0')  # 0表示没有删除
    parent = models.ForeignKey('self',  #todo self:自己和自己关联
                               blank=True,
                               null=True,
                               related_name='children', #反向关联的属性
                               on_delete=models.CASCADE)    #当删除的时候作级联删除

    class Meta:
        db_table = 't_menu'
        verbose_name = '功能菜单表'
        verbose_name_plural = verbose_name
        ordering = ['number']

    def __str__(self):
        return self.name

三、功能菜单视图类设计

1、都有那些视图?

1、新增-create
2、查询单个功能菜单 retrieve
3、查询所有功能菜单-list
4、查询某个父菜单下面的所有子菜单
5、查询所有的顶级菜单列表(一级菜单)
6、删除某一个功能菜单-destroy
7、批量删除多个功能菜单,传参:ids=[1,2,3]
8、修改功能菜单-update

查询所有菜单列表,不需要传递参数
查询某个父菜单下面的所有子菜单,需要传递一个参数,pid(父菜单id)
pid=0表示查询所有顶级菜单列表

class MenuView(ModelViewSet):
    """
    create:
    新增菜单,

    参数:为Menu对象,其中delete_flag,create_time,update_time不用传参,return:添加之后的对象

    retrieve:
    查询单个菜单对象

    list:
    查询所有的菜单

    如果参数中有pid,则查询某一个父菜单下的所有子菜单列表,pid=0表示查询顶级菜单列表

    update:
    修改菜单

    destroy:
    删除某个菜单

    partial_update:
    局部修改菜单,修改任意的某个或者某几个属性
    """
    queryset = MenuModel.objects.filter(delete_flag=0).all()
    serializer_class = MenuSerializer
    # permission_classes = [IsAuthenticated]

    def get_queryset(self):
        print(self.request.user)
        logger.info(f'当前登录的用户是:{self.request.user}')

        # query_params = self.request.query_params.get('pid', None)
        query_params = self.request.GET.get('pid', None)
        if query_params:
            pid = int(query_params)
            if pid == 0:  # 查询所有顶级菜单
                return MenuModel.objects.filter(parent__isnull=True, delete_flag=0).all()
            else:  # 查询某个父菜单下面的所有子菜单
                return MenuModel.objects.filter(parent_id=pid, delete_flag=0).all()
        else:
            return MenuModel.objects.filter(delete_flag=0).all()

2、删除单个菜单的注意点

1、删除数据并不是真正的将数据删除(数据库中的数据清掉),而是将该数据的delete_flag设置为1;
而原始的ModelViewSet视图类中提供的destroy方法是将数据从数据库中删除。所以需要重写该方法;

2、当删除父级菜单时,当前父级菜单下的所有子级菜单也需要删除

3、menu.save():容易忽视

    def destroy(self, request, *args, **kwargs):
        '''修改下删除的标记为:delete_flag=1'''
        menu = self.get_object()
        menu.delete_flag = 1  # 修改属性
        menu.save()
        # 可能该菜单下面还有很多子菜单,这些子菜单也需要修改
        MenuModel.objects.filter(parent_id=menu.id).update(delete_flag=1)
        return Response(status=status.HTTP_204_NO_CONTENT)

3、action装饰器的使用

action装饰器接收2个参数:methods和detail
methods:声明该action对应的请求方式,列表传递;传递的方法包含post、delete、update、put
detail:声明该action的路径是否与单一资源对应
当detail为True:表示的路径为:xxx/<pk>/action方法名称
当detail为False:表示的路径为:xxx/action方法名称

4、批量删除多个菜单的注意点

1、前端以json格式的数据传递,后端需要用request.data.get()去接收
2、传递的参数格式是列表,后端需要校验数据类型
3、删除父级菜单,同时也需要删除父级菜单下的所有子级菜单

    @action(methods=['delete'], detail=False)
    def multiple_delete(self, request, *args, **kwargs):
        delete_ids = request.data.get('ids')    #json格式传递过来的
        if not delete_ids:
            return Response(data={'detail': '参数错误,ids为必填参数'}, status=status.HTTP_204_NO_CONTENT)
        elif not isinstance(delete_ids, list):
            return Response(data={'detail': '参数错误,ids必须为列表'}, status=status.HTTP_204_NO_CONTENT)

        # 先删除传递过来的菜单
        MenuModel.objects.filter(id__in=delete_ids).update(delete_flag='1')
        # 后删除所有的子菜单
        for m_id in delete_ids:
            MenuModel.objects.filter(parent_id=m_id).update(delete_flag='1')
        return Response(status=status.HTTP_204_NO_CONTENT)

四、路由的配置

from django.urls import path,re_path,include
from . import views
from rest_framework import routers
from erp_system.views.menu import MenuView
router=routers.DefaultRouter()

router.register(r'menus',MenuView)

urlpatterns = [
    re_path(r'',include(router.urls)),

]

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/101823.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

HFSS使用经验二

目录 一、绘制空气盒 二、Driven Solution Setup 的设置 ​三、如何添加圆场放大图 四、仿真之前的Validate 五、开始仿真 六、仿真过程Solution Data的查看 一、绘制空气盒 选择Padding type为Absolute Offset 设定Boundary为Radiation辐射边界 空气盒比较大&#xff…

数据校验-springboot

前置知识 先了解一下JSR、Hibernate Validator、Spring Validation&#xff1a; JSR&#xff08;Java Specification Request&#xff09;规范是Java EE 6中的一项子规范&#xff0c;也叫作Bean Validation。它指定了一整套基于bean的验证API&#xff0c;通过标注给对象属性添…

数据可视化之中国足球队在国际足联及亚洲的历史排名看这儿

最近最热的体育盛事莫过于世界杯了&#xff0c;四年一届的足球盛事&#xff0c;正在卡塔尔激战正酣。这时候可能会有球迷疑问&#xff1a;怎么没看到中国队呢&#xff1f;也有网友调侃说中国队被分到工程队去了。 泱泱大国&#xff0c;难道中国十几亿人口&#xff0c;一个足球队…

【Javassist】快速入门系列02 使用Javassist实现方法执行时间统计

系列文章目录 01 在方法体的开头或结尾插入代码 02 使用Javassist实现方法执行时间统计 前言 上一章我们介绍了使用Javassist实现一个简单的Hello World程序&#xff0c;学会了Javassist创建类和新增方法。本章主要介绍如何使用Javassist实现一个无侵入的方法执行时间统计 …

DCN神州数码——DHCP相关操作指令(超详细)

DHCP服务器配置 service dhcp 启动DHCP 服务器或中继功能 ip dhcp pool pool1 network-address 1.1.1.1 24 default-router dns-server 8.8.8.8 domain-name dcn.com netbios-name-server 2.2.2.2 lease 5 ip dhcp excluded-address 2.2.2.2 创建DHCP地址池pool1配置地…

PHP反序列化详解(一)——反序列化基础

今天继续给大家介绍渗透测试相关知识&#xff0c;本文主要内容是PHP反序列化详解&#xff08;一&#xff09;——反序列化基础。 免责声明&#xff1a; 本文所介绍的内容仅做学习交流使用&#xff0c;严禁利用文中技术进行非法行为&#xff0c;否则造成一切严重后果自负&#x…

西藏旅行网站

开发工具(eclipse/idea/vscode等)&#xff1a; 数据库(sqlite/mysql/sqlserver等)&#xff1a; 功能模块(请用文字描述&#xff0c;至少200字)&#xff1a; (1)旅游线路信息发布以及预定功能&#xff1a;顾客可通网站查看相应的旅游线路信息 和预定旅游线路功能&#xff0c;管理…

OpenCV(8)-OpenCV中的形态学

OpenCV中的形态学 形态学概述 什么是形态学处理&#xff1a; 基于图像形态进行处理的一些基本方法 这些处理方法基本上是对二进制图像进行处理卷积核决定这图像处理后的效果基本方法&#xff1a; 腐蚀与膨胀开运算闭运算顶帽黑帽 图像二值化 将图像的每个像素变成两种值&a…

服务器设置tomcat开机自启动(cmd命令行语句)

1 找到tomcat安装目录&#xff0c;进入bin/文件夹下面&#xff0c;在此打开windows 命令行窗口。 2 输入 service install tomcatXXX将tomcat注册成为windows服务&#xff0c;其中tomcatXXX为服务名。 3查看刚刚注册的服务 “我的电脑”-》右键管理 发现刚刚的服务是手动的&…

DevOps-6:Jenkins使用技巧

1、如何提升Jenkins的Job并行构建数 默认情况下&#xff0c;Jenkins只配置了2个Executor&#xff0c;即只允许最多2个Job同时构建&#xff0c;这个值可以修改&#xff1a; 在Manage Jenkins>Configure System里&#xff0c;找到 # of executors&#xff0c;修改这个值就好&…

DW学生美食网页设计作业——餐饮美食汉堡企业网站6页面带轮播(HTML+CSS+JavaScript)

&#x1f468;‍&#x1f393;静态网站的编写主要是用HTML DIVCSS JS等来完成页面的排版设计&#x1f469;‍&#x1f393;,常用的网页设计软件有Dreamweaver、EditPlus、HBuilderX、VScode 、Webstorm、Animate等等&#xff0c;用的最多的还是DW&#xff0c;当然不同软件写出的…

cython混淆加密

python代码是一种解释型的语言&#xff0c;有了代码和环境就可以执行&#xff0c;它无需编译。如果需要对代码进行混淆&#xff0c;可以借助cython这个库。它的安装很简单&#xff0c;直接运行pip install cython就可以安装。 进行代码混淆之前&#xff0c;还需要一个环境&…

windows下编译libevent源码

《Linux下编译libevent源码》讲述了linux下编译libevent源码的方法&#xff0c;本文讲述其在windows平台的编译。 一、下载libevent源码 https://libevent.org/ 下载libevent源码并解压。 二.安装依赖项 下载安装OpenSSL。https://slproweb.com/products/Win32OpenSSL.html 三…

MySQL8.0高级篇(下)-事务与日志和备份

文章目录一、事务基础知识1、数据库事务概述1.1 基本概念1.2 事物的ACID特性1.3 事务的状态2、如何使用事务2.1 显式事务2.2 隐式事务2.3 隐式提交数据的情况2.4 使用举例3、事务隔离级别3.1 数据准备3.2 数据并发问题3.3 SQL中的四种隔离级别3.4 MySQL支持的四种隔离级别4、事…

【实时数仓】DWM层订单宽表之需求分析、订单和订单明细关联源码

文章目录一 DWM层-订单宽表1 需求分析与思路2 订单和订单明细关联代码实现&#xff08;1&#xff09;从Kafka的dwd层接收订单和订单明细数据a 创建订单实体类b 创建订单明细实体类c 在dwm包下创建OrderWideApp读取订单和订单明细数据d 测试&#xff08;2&#xff09;订单和订单…

SpringBoot中的starter:whywhatmake

1、为什么用starter 我们知道&#xff0c;springboot框架是为了简化spring框架开发推出的&#xff0c;那么&#xff0c;在之前的spring框架开发中&#xff0c;如果我们需要连接数据库&#xff0c;引入mybatis框架&#xff0c;需要怎么操作呢&#xff1f;我们需要去maven仓库找…

当 chatGPT 被职场 PUA ,笑麻了

大家最近是不是被 chatGPT 刷屏了&#xff1f;简单来说&#xff0c;chatGPT 是一个智能聊天引擎。 那 chatGPT 和小爱同学、 siri 有什么区别呢&#xff1f; 如果体验过的朋友&#xff0c;能感受到区别还是很大&#xff0c;chatGPT 的智能表现过于优秀&#xff0c;远远超过了这…

深入浅出DPDK KNI核心技术

一、KNI KNI全称&#xff1a;Kernel NIC Interface&#xff0c;内核网卡接口&#xff0c;允许用户态程序访问linux控制平面。 在DPDK报文处理中&#xff0c;有些报文需要发送到内核协议栈进行处理&#xff0c;如GTP-C控制报文 如果报文数量较少&#xff0c;可以使用内核提供…

Lua热更新

Lua热更新解决方案 文章目录Lua热更新解决方案1.AB包1.1 AB包概述1. 从0开始的Lua语法1.1 HelloWorld1.2 数据类型1.3 字符串1.4 运算符1.5 条件语句1.6 循环语句1.7 函数1.8 数组1.9 迭代器1.10 字典&#xff0c;类&#xff0c;对象1.11 多脚本执行1.12 特殊语法1.13 协程1.14…

hive时间和字符串互转,时间函数

hive里经常需要将字符串转化为date或timestamp 或者转化为日期格式的string 先说一个简单的 cast(xx as date/string/timestamp) 这个大多情况都可以用 1.to_date to_date只保留年月日,参数必须是string类型的yyyy-MM-dd HH:mm:ss或者date或timestamp类型,返回值是date类型,…