智慧水务项目(三)django(drf)+angular 18 创建系统管理的用户、角色、部门、权限管理等model

一、说明

添加各model

添加requirement.txt中的库

添加env.py中的动态配置

二、env.py全文

import os
from smartwater.settings import BASE_DIR# ================================================= #
# ************** mysql数据库 配置  ************** #
# ================================================= #
# 数据库地址
DATABASE_ENGINE = "django.db.backends.mysql"
# 数据库地址
DATABASE_HOST = "mysql.sqlpub.com"
# 数据库端口
DATABASE_PORT = 3306
# 数据库用户名
DATABASE_USER = "smartwater"
# 数据库密码
DATABASE_PASSWORD = ""
# 数据库名
DATABASE_NAME = "smartwater"
#数据库编码
DATABASE_CHARSET = "utf8mb4"
# 数据库长连接时间(默认为0,单位秒)即每次请求都重新连接,debug模式下该值应该写为0 ,mysql默认长连接超时时间为8小时
DATABASE_CONN_MAX_AGE = 0 #推荐120(2分钟),使用 None 则是无限的持久连接(不推荐)。# 表前缀
TABLE_PREFIX = "sw_"# ================================================= #
# ****************** 功能 启停  ******************* #
# ================================================= #
DEBUG = True
# 启动登录详细概略获取(通过调用api获取ip详细地址。如果是内网,关闭即可)
ENABLE_LOGIN_ANALYSIS_LOG = True
# 登录接口 /api/token/ 是否需要验证码认证,用于测试,正式环境建议取消
LOGIN_NO_CAPTCHA_AUTH = True
# ================================================= #
# ****************** 其他 配置  ******************* #
# ================================================= #ALLOWED_HOSTS = ["*"]
# 列权限中排除App应用
COLUMN_EXCLUDE_APPS = []

三、settings.py全文

 目录如下(添加了log,还没测试,先加在这里)

全文如下

"""
Django settings for smartwater project.Generated by 'django-admin startproject' using Django 5.0.7.For more information on this file, see
https://docs.djangoproject.com/en/5.0/topics/settings/For the full list of settings and their values, see
https://docs.djangoproject.com/en/5.0/ref/settings/
"""import os
import sys
from pathlib import Path
from datetime import timedelta# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent# ******************** 动态配置 ******************** #
# ================================================= #from env import *# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/5.0/howto/deployment/checklist/# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'django-insecure-_+uhlssu=*ql)o(bh=@cug4@9*l+)nt^w3y&f(bk8&-3cerw#m'# SECURITY WARNING: don't run with debug turned on in production!DEBUG = locals().get("DEBUG", True)
ALLOWED_HOSTS = locals().get("ALLOWED_HOSTS", ["*"])# 列权限需要排除的App应用
COLUMN_EXCLUDE_APPS = ['channels', 'captcha'] + locals().get("COLUMN_EXCLUDE_APPS", [])# Application definitionINSTALLED_APPS = ['django.contrib.admin','django.contrib.auth','django.contrib.contenttypes','django.contrib.sessions','django.contrib.messages','django.contrib.staticfiles','rest_framework','corsheaders','apps.system',]MIDDLEWARE = ['django.middleware.security.SecurityMiddleware','django.contrib.sessions.middleware.SessionMiddleware','django.middleware.common.CommonMiddleware','django.middleware.csrf.CsrfViewMiddleware','django.contrib.auth.middleware.AuthenticationMiddleware','django.contrib.messages.middleware.MessageMiddleware','django.middleware.clickjacking.XFrameOptionsMiddleware',"corsheaders.middleware.CorsMiddleware",  # 跨域中间件
]ROOT_URLCONF = 'smartwater.urls'TEMPLATES = [{'BACKEND': 'django.template.backends.django.DjangoTemplates','DIRS': [],'APP_DIRS': True,'OPTIONS': {'context_processors': ['django.template.context_processors.debug','django.template.context_processors.request','django.contrib.auth.context_processors.auth','django.contrib.messages.context_processors.messages',],},},
]ASGI_APPLICATION = 'smartwater.asgi.application'
WSGI_APPLICATION = 'smartwater.wsgi.application'# Database
# https://docs.djangoproject.com/en/5.0/ref/settings/#databasesDATABASES = {'default': {'ENGINE': DATABASE_ENGINE,'NAME': DATABASE_NAME,'USER': DATABASE_USER,'PASSWORD': DATABASE_PASSWORD,'HOST': DATABASE_HOST,'PORT': DATABASE_PORT,'CONN_MAX_AGE': DATABASE_CONN_MAX_AGE,'OPTIONS': {'charset': DATABASE_CHARSET,'init_command': 'SET default_storage_engine=INNODB',  # innodb才支持事务}}
}AUTH_USER_MODEL = 'system.Users'
USERNAME_FIELD = 'username'
ALL_MODELS_OBJECTS = []  # 所有app models 对象# Password validation
# https://docs.djangoproject.com/en/5.0/ref/settings/#auth-password-validatorsAUTH_PASSWORD_VALIDATORS = [{'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',},{'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',},{'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',},{'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',},
]# Internationalization
# https://docs.djangoproject.com/en/5.0/topics/i18n/LANGUAGE_CODE = "zh-hans"TIME_ZONE = "Asia/Shanghai"USE_I18N = TrueUSE_L10N = TrueUSE_TZ = False# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/5.0/howto/static-files/STATIC_URL = 'static/'# Default primary key field type
# https://docs.djangoproject.com/en/5.0/ref/settings/#default-auto-fieldDEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'# ================================================= #
# ******************* 跨域的配置 ******************* #
# ================================================= ## 白名单
# CORS_ORIGIN_WHITELIST = (
#     'http://127.0.0.1:8000',
#     'http://127.0.0.1:8080',
#     'http://localhost:8000',
#     'http://localhost:8080',
# )
# 全部允许配置
CORS_ORIGIN_ALLOW_ALL = True
# 允许cookie
CORS_ALLOW_CREDENTIALS = True  # 指明在跨域访问中,后端是否支持对cookie的操作ALL_MODELS_OBJECTS = []  # 所有app models 对象# ================================================= #
# ********************* 日志配置 ******************* #
# ================================================= #
# # log 配置部分BEGIN #
SERVER_LOGS_FILE = os.path.join(BASE_DIR, "logs", "server.log")
ERROR_LOGS_FILE = os.path.join(BASE_DIR, "logs", "error.log")
LOGS_FILE = os.path.join(BASE_DIR, "logs")
if not os.path.exists(os.path.join(BASE_DIR, "logs")):os.makedirs(os.path.join(BASE_DIR, "logs"))# 格式:[2020-04-22 23:33:01][micoservice.apps.ready():16] [INFO] 这是一条日志:
# 格式:[日期][模块.函数名称():行号] [级别] 信息
STANDARD_LOG_FORMAT = ("[%(asctime)s][%(name)s.%(funcName)s():%(lineno)d] [%(levelname)s] %(message)s"
)
CONSOLE_LOG_FORMAT = ("[%(asctime)s][%(name)s.%(funcName)s():%(lineno)d] [%(levelname)s] %(message)s"
)
LOGGING = {"version": 1,"disable_existing_loggers": False,"formatters": {"standard": {"format": STANDARD_LOG_FORMAT},"console": {"format": CONSOLE_LOG_FORMAT,"datefmt": "%Y-%m-%d %H:%M:%S",},"file": {"format": CONSOLE_LOG_FORMAT,"datefmt": "%Y-%m-%d %H:%M:%S",},},"handlers": {"file": {"level": "INFO","class": "logging.handlers.RotatingFileHandler","filename": SERVER_LOGS_FILE,"maxBytes": 1024 * 1024 * 100,  # 100 MB"backupCount": 5,  # 最多备份5个"formatter": "standard","encoding": "utf-8",},"error": {"level": "ERROR","class": "logging.handlers.RotatingFileHandler","filename": ERROR_LOGS_FILE,"maxBytes": 1024 * 1024 * 100,  # 100 MB"backupCount": 3,  # 最多备份3个"formatter": "standard","encoding": "utf-8",},"console": {"level": "INFO","class": "logging.StreamHandler","formatter": "console",},},"loggers": {"": {"handlers": ["console", "error", "file"],"level": "INFO",},"django": {"handlers": ["console", "error", "file"],"level": "INFO","propagate": False,},'django.db.backends': {'handlers': ["console", "error", "file"],'propagate': False,'level': "INFO"},"uvicorn.error": {"level": "INFO","handlers": ["console", "error", "file"],},"uvicorn.access": {"handlers": ["console", "error", "file"],"level": "INFO"},},
}# ================================================= #
# *************** REST_FRAMEWORK配置 *************** #
# ================================================= #REST_FRAMEWORK = {'DEFAULT_PARSER_CLASSES': ('rest_framework.parsers.JSONParser','rest_framework.parsers.MultiPartParser',),"DATETIME_FORMAT": "%Y-%m-%d %H:%M:%S",  # 日期时间格式配置"DATE_FORMAT": "%Y-%m-%d",}

四、requirements.txt全文

Django
django-comment-migrate
django-cors-headers
django-filter
django-ranged-response
djangorestframework
django-restql
django-simple-captcha
django-timezone-field
djangorestframework-simplejwt
drf-yasg
mysqlclient
ua-parser
pyparsing
openpyxl
requests
typing-extensions
tzlocal
channels
channels-redis
websockets
user-agents
six
whitenoise
Pillow

五、添加model

目录看图

全文

import hashlib
import osfrom django.contrib.auth.models import AbstractUser, UserManager
from django.core.exceptions import ObjectDoesNotExist, ValidationError
from django.db import models
from apps.utils.db import BaseModel, table_prefixclass Role(BaseModel):name = models.CharField(max_length=64, verbose_name="角色名称", help_text="角色名称")key = models.CharField(max_length=64, unique=True, verbose_name="权限字符", help_text="权限字符")sort = models.IntegerField(default=1, verbose_name="角色顺序", help_text="角色顺序")status = models.BooleanField(default=True, verbose_name="角色状态", help_text="角色状态")class Meta:db_table = table_prefix + "role"verbose_name = "角色表"verbose_name_plural = verbose_nameordering = ("sort",)class CustomUserManager(UserManager):def create_superuser(self, username, email=None, password=None, **extra_fields):user = super(CustomUserManager, self).create_superuser(username, email, password, **extra_fields)user.set_password(password)try:user.role.add(Role.objects.get(name="管理员"))user.save(using=self._db)return userexcept ObjectDoesNotExist:user.delete()raise ValidationError("角色`管理员`不存在, 创建失败, 请先执行python manage.py init")class Post(BaseModel):name = models.CharField(null=False, max_length=64, verbose_name="岗位名称", help_text="岗位名称")code = models.CharField(max_length=32, verbose_name="岗位编码", help_text="岗位编码")sort = models.IntegerField(default=1, verbose_name="岗位顺序", help_text="岗位顺序")STATUS_CHOICES = ((0, "离职"),(1, "在职"),)status = models.IntegerField(choices=STATUS_CHOICES, default=1, verbose_name="岗位状态", help_text="岗位状态")class Meta:db_table = table_prefix + "post"verbose_name = "岗位表"verbose_name_plural = verbose_nameordering = ("sort",)class Dept(BaseModel):name = models.CharField(max_length=64, verbose_name="部门名称", help_text="部门名称")key = models.CharField(max_length=64, unique=True, null=True, blank=True, verbose_name="关联字符",help_text="关联字符")sort = models.IntegerField(default=1, verbose_name="显示排序", help_text="显示排序")owner = models.CharField(max_length=32, verbose_name="负责人", null=True, blank=True, help_text="负责人")phone = models.CharField(max_length=32, verbose_name="联系电话", null=True, blank=True, help_text="联系电话")email = models.EmailField(max_length=32, verbose_name="邮箱", null=True, blank=True, help_text="邮箱")status = models.BooleanField(default=True, verbose_name="部门状态", null=True, blank=True, help_text="部门状态")parent = models.ForeignKey(to="Dept",on_delete=models.CASCADE,default=None,verbose_name="上级部门",db_constraint=False,null=True,blank=True,help_text="上级部门",)@classmethoddef recursion_all_dept(cls, dept_id: int, dept_all_list=None, dept_list=None):"""递归获取部门的所有下级部门:param dept_id: 需要获取的id:param dept_all_list: 所有列表:param dept_list: 递归list:return:"""if not dept_all_list:dept_all_list = Dept.objects.values("id", "parent")if dept_list is None:dept_list = [dept_id]for ele in dept_all_list:if ele.get("parent") == dept_id:dept_list.append(ele.get("id"))cls.recursion_all_dept(ele.get("id"), dept_all_list, dept_list)return list(set(dept_list))class Meta:db_table = table_prefix + "dept"verbose_name = "部门表"verbose_name_plural = verbose_nameordering = ("sort",)class Users(BaseModel, AbstractUser):username = models.CharField(max_length=150, unique=True, db_index=True, verbose_name="用户账号",help_text="用户账号")email = models.EmailField(max_length=255, verbose_name="邮箱", null=True, blank=True, help_text="邮箱")mobile = models.CharField(max_length=255, verbose_name="电话", null=True, blank=True, help_text="电话")avatar = models.CharField(max_length=255, verbose_name="头像", null=True, blank=True, help_text="头像")name = models.CharField(max_length=40, verbose_name="姓名", help_text="姓名")GENDER_CHOICES = ((0, "未知"),(1, "男"),(2, "女"),)gender = models.IntegerField(choices=GENDER_CHOICES, default=0, verbose_name="性别", null=True, blank=True, help_text="性别")USER_TYPE = ((0, "后台用户"),(1, "前台用户"),)user_type = models.IntegerField(choices=USER_TYPE, default=0, verbose_name="用户类型", null=True, blank=True, help_text="用户类型")post = models.ManyToManyField(to="Post", blank=True, verbose_name="关联岗位", db_constraint=False,help_text="关联岗位")role = models.ManyToManyField(to="Role", blank=True, verbose_name="关联角色", db_constraint=False,help_text="关联角色")dept = models.ForeignKey(to="Dept",verbose_name="所属部门",on_delete=models.PROTECT,db_constraint=False,null=True,blank=True,help_text="关联部门",)login_error_count = models.IntegerField(default=0, verbose_name="登录错误次数", help_text="登录错误次数")objects = CustomUserManager()def set_password(self, raw_password):super().set_password(hashlib.md5(raw_password.encode(encoding="UTF-8")).hexdigest())class Meta:db_table = table_prefix + "users"verbose_name = "用户表"verbose_name_plural = verbose_nameordering = ("-create_datetime",)class Menu(BaseModel):parent = models.ForeignKey(to="Menu",on_delete=models.CASCADE,verbose_name="上级菜单",null=True,blank=True,db_constraint=False,help_text="上级菜单",)icon = models.CharField(max_length=64, verbose_name="菜单图标", null=True, blank=True, help_text="菜单图标")name = models.CharField(max_length=64, verbose_name="菜单名称", help_text="菜单名称")sort = models.IntegerField(default=1, verbose_name="显示排序", null=True, blank=True, help_text="显示排序")ISLINK_CHOICES = ((0, "否"),(1, "是"),)is_link = models.BooleanField(default=False, verbose_name="是否外链", help_text="是否外链")link_url = models.CharField(max_length=255, verbose_name="链接地址", null=True, blank=True, help_text="链接地址")is_catalog = models.BooleanField(default=False, verbose_name="是否目录", help_text="是否目录")web_path = models.CharField(max_length=128, verbose_name="路由地址", null=True, blank=True, help_text="路由地址")component = models.CharField(max_length=128, verbose_name="组件地址", null=True, blank=True, help_text="组件地址")component_name = models.CharField(max_length=50, verbose_name="组件名称", null=True, blank=True,help_text="组件名称")status = models.BooleanField(default=True, blank=True, verbose_name="菜单状态", help_text="菜单状态")cache = models.BooleanField(default=False, blank=True, verbose_name="是否页面缓存", help_text="是否页面缓存")visible = models.BooleanField(default=True, blank=True, verbose_name="侧边栏中是否显示",help_text="侧边栏中是否显示")is_iframe = models.BooleanField(default=False, blank=True, verbose_name="框架外显示", help_text="框架外显示")is_affix = models.BooleanField(default=False, blank=True, verbose_name="是否固定", help_text="是否固定")@classmethoddef get_all_parent(cls, id: int, all_list=None, nodes=None):"""递归获取给定ID的所有层级:param id: 参数ID:param all_list: 所有列表:param nodes: 递归列表:return: nodes"""if not all_list:all_list = Menu.objects.values("id", "name", "parent")if nodes is None:nodes = []for ele in all_list:if ele.get("id") == id:parent_id = ele.get("parent")if parent_id is not None:cls.get_all_parent(parent_id, all_list, nodes)nodes.append(ele)return nodesclass Meta:db_table = table_prefix + "menu"verbose_name = "菜单表"verbose_name_plural = verbose_nameordering = ("sort",)class MenuField(BaseModel):model = models.CharField(max_length=64, verbose_name='表名')menu = models.ForeignKey(to='Menu', on_delete=models.CASCADE, verbose_name='菜单', db_constraint=False)field_name = models.CharField(max_length=64, verbose_name='模型表字段名')title = models.CharField(max_length=64, verbose_name='字段显示名')class Meta:db_table = table_prefix + "menu_field"verbose_name = "菜单字段表"verbose_name_plural = verbose_nameordering = ("id",)class FieldPermission(BaseModel):role = models.ForeignKey(to='Role', on_delete=models.CASCADE, verbose_name='角色', db_constraint=False)field = models.ForeignKey(to='MenuField', on_delete=models.CASCADE, related_name='menu_field', verbose_name='字段', db_constraint=False)is_query = models.BooleanField(default=1, verbose_name='是否可查询')is_create = models.BooleanField(default=1, verbose_name='是否可创建')is_update = models.BooleanField(default=1, verbose_name='是否可更新')class Meta:db_table = table_prefix + "field_permission"verbose_name = "字段权限表"verbose_name_plural = verbose_nameordering = ("id",)class MenuButton(BaseModel):menu = models.ForeignKey(to="Menu",db_constraint=False,related_name="menuPermission",on_delete=models.CASCADE,verbose_name="关联菜单",help_text="关联菜单",)name = models.CharField(max_length=64, verbose_name="名称", help_text="名称")value = models.CharField(unique=True, max_length=64, verbose_name="权限值", help_text="权限值")api = models.CharField(max_length=200, verbose_name="接口地址", help_text="接口地址")METHOD_CHOICES = ((0, "GET"),(1, "POST"),(2, "PUT"),(3, "DELETE"),)method = models.IntegerField(default=0, verbose_name="接口请求方法", null=True, blank=True,help_text="接口请求方法")class Meta:db_table = table_prefix + "menu_button"verbose_name = "菜单权限表"verbose_name_plural = verbose_nameordering = ("-name",)class RoleMenuPermission(BaseModel):role = models.ForeignKey(to="Role",db_constraint=False,related_name="role_menu",on_delete=models.CASCADE,verbose_name="关联角色",help_text="关联角色",)menu = models.ForeignKey(to="Menu",db_constraint=False,related_name="role_menu",on_delete=models.CASCADE,verbose_name="关联菜单",help_text="关联菜单",)class Meta:db_table = table_prefix + "role_menu_permission"verbose_name = "角色菜单权限表"verbose_name_plural = verbose_name# ordering = ("-create_datetime",)class RoleMenuButtonPermission(BaseModel):role = models.ForeignKey(to="Role",db_constraint=False,related_name="role_menu_button",on_delete=models.CASCADE,verbose_name="关联角色",help_text="关联角色",)menu_button = models.ForeignKey(to="MenuButton",db_constraint=False,related_name="menu_button_permission",on_delete=models.CASCADE,verbose_name="关联菜单按钮",help_text="关联菜单按钮",null=True,blank=True)DATASCOPE_CHOICES = ((0, "仅本人数据权限"),(1, "本部门及以下数据权限"),(2, "本部门数据权限"),(3, "全部数据权限"),(4, "自定数据权限"),)data_range = models.IntegerField(default=0, choices=DATASCOPE_CHOICES, verbose_name="数据权限范围",help_text="数据权限范围")dept = models.ManyToManyField(to="Dept", blank=True, verbose_name="数据权限-关联部门", db_constraint=False,help_text="数据权限-关联部门")class Meta:db_table = table_prefix + "role_menu_button_permission"verbose_name = "角色按钮权限表"verbose_name_plural = verbose_nameordering = ("-create_datetime",)class Dictionary(BaseModel):TYPE_LIST = ((0, "text"),(1, "number"),(2, "date"),(3, "datetime"),(4, "time"),(5, "files"),(6, "boolean"),(7, "images"),)label = models.CharField(max_length=100, blank=True, null=True, verbose_name="字典名称", help_text="字典名称")value = models.CharField(max_length=200, blank=True, null=True, verbose_name="字典编号", help_text="字典编号/实际值")parent = models.ForeignKey(to="self",related_name="sublist",db_constraint=False,on_delete=models.PROTECT,blank=True,null=True,verbose_name="父级",help_text="父级",)type = models.IntegerField(choices=TYPE_LIST, default=0, verbose_name="数据值类型", help_text="数据值类型")color = models.CharField(max_length=20, blank=True, null=True, verbose_name="颜色", help_text="颜色")is_value = models.BooleanField(default=False, verbose_name="是否为value值",help_text="是否为value值,用来做具体值存放")status = models.BooleanField(default=True, verbose_name="状态", help_text="状态")sort = models.IntegerField(default=1, verbose_name="显示排序", null=True, blank=True, help_text="显示排序")remark = models.CharField(max_length=2000, blank=True, null=True, verbose_name="备注", help_text="备注")class Meta:db_table = table_prefix + "dictionary"verbose_name = "字典表"verbose_name_plural = verbose_nameordering = ("sort",)def save(self, force_insert=False, force_update=False, using=None, update_fields=None):super().save(force_insert, force_update, using, update_fields)# dispatch.refresh_dictionary()  # 有更新则刷新字典配置def delete(self, using=None, keep_parents=False):res = super().delete(using, keep_parents)# dispatch.refresh_dictionary()return resclass OperationLog(BaseModel):request_modular = models.CharField(max_length=64, verbose_name="请求模块", null=True, blank=True,help_text="请求模块")request_path = models.CharField(max_length=400, verbose_name="请求地址", null=True, blank=True,help_text="请求地址")request_body = models.TextField(verbose_name="请求参数", null=True, blank=True, help_text="请求参数")request_method = models.CharField(max_length=8, verbose_name="请求方式", null=True, blank=True,help_text="请求方式")request_msg = models.TextField(verbose_name="操作说明", null=True, blank=True, help_text="操作说明")request_ip = models.CharField(max_length=32, verbose_name="请求ip地址", null=True, blank=True,help_text="请求ip地址")request_browser = models.CharField(max_length=64, verbose_name="请求浏览器", null=True, blank=True,help_text="请求浏览器")response_code = models.CharField(max_length=32, verbose_name="响应状态码", null=True, blank=True,help_text="响应状态码")request_os = models.CharField(max_length=64, verbose_name="操作系统", null=True, blank=True, help_text="操作系统")json_result = models.TextField(verbose_name="返回信息", null=True, blank=True, help_text="返回信息")status = models.BooleanField(default=False, verbose_name="响应状态", help_text="响应状态")class Meta:db_table = table_prefix + "operation_log"verbose_name = "操作日志"verbose_name_plural = verbose_nameordering = ("-create_datetime",)def media_file_name(instance, filename):h = instance.md5sumbasename, ext = os.path.splitext(filename)return os.path.join("files", h[:1], h[1:2], h + ext.lower())class FileList(BaseModel):name = models.CharField(max_length=200, null=True, blank=True, verbose_name="名称", help_text="名称")url = models.FileField(upload_to=media_file_name, null=True, blank=True,)file_url = models.CharField(max_length=255, blank=True, verbose_name="文件地址", help_text="文件地址")engine = models.CharField(max_length=100, default='local', blank=True, verbose_name="引擎", help_text="引擎")mime_type = models.CharField(max_length=100, blank=True, verbose_name="Mime类型", help_text="Mime类型")size = models.CharField(max_length=36, blank=True, verbose_name="文件大小", help_text="文件大小")md5sum = models.CharField(max_length=36, blank=True, verbose_name="文件md5", help_text="文件md5")def save(self, *args, **kwargs):if not self.md5sum:  # file is newmd5 = hashlib.md5()for chunk in self.url.chunks():md5.update(chunk)self.md5sum = md5.hexdigest()if not self.size:self.size = self.url.sizeif not self.file_url:url = media_file_name(self, self.name)self.file_url = f'media/{url}'super(FileList, self).save(*args, **kwargs)class Meta:db_table = table_prefix + "file_list"verbose_name = "文件管理"verbose_name_plural = verbose_nameordering = ("-create_datetime",)class Area(BaseModel):name = models.CharField(max_length=100, verbose_name="名称", help_text="名称")code = models.CharField(max_length=20, verbose_name="地区编码", help_text="地区编码", unique=True, db_index=True)level = models.BigIntegerField(verbose_name="地区层级(1省份 2城市 3区县 4乡级)",help_text="地区层级(1省份 2城市 3区县 4乡级)")pinyin = models.CharField(max_length=255, verbose_name="拼音", help_text="拼音")initials = models.CharField(max_length=20, verbose_name="首字母", help_text="首字母")enable = models.BooleanField(default=True, verbose_name="是否启用", help_text="是否启用")pcode = models.ForeignKey(to="self",verbose_name="父地区编码",to_field="code",on_delete=models.CASCADE,db_constraint=False,null=True,blank=True,help_text="父地区编码",)class Meta:db_table = table_prefix + "area"verbose_name = "地区表"verbose_name_plural = verbose_nameordering = ("code",)def __str__(self):return f"{self.name}"class ApiWhiteList(BaseModel):url = models.CharField(max_length=200, help_text="url地址", verbose_name="url")METHOD_CHOICES = ((0, "GET"),(1, "POST"),(2, "PUT"),(3, "DELETE"),)method = models.IntegerField(default=0, verbose_name="接口请求方法", null=True, blank=True,help_text="接口请求方法")enable_datasource = models.BooleanField(default=True, verbose_name="激活数据权限", help_text="激活数据权限",blank=True)class Meta:db_table = table_prefix + "api_white_list"verbose_name = "接口白名单"verbose_name_plural = verbose_nameordering = ("-create_datetime",)class SystemConfig(BaseModel):parent = models.ForeignKey(to="self",verbose_name="父级",on_delete=models.CASCADE,db_constraint=False,null=True,blank=True,help_text="父级",)title = models.CharField(max_length=50, verbose_name="标题", help_text="标题")key = models.CharField(max_length=100, verbose_name="键", help_text="键", db_index=True)value = models.JSONField(max_length=100, verbose_name="值", help_text="值", null=True, blank=True)sort = models.IntegerField(default=0, verbose_name="排序", help_text="排序", blank=True)status = models.BooleanField(default=True, verbose_name="启用状态", help_text="启用状态")data_options = models.JSONField(verbose_name="数据options", help_text="数据options", null=True, blank=True)FORM_ITEM_TYPE_LIST = ((0, "text"),(1, "datetime"),(2, "date"),(3, "textarea"),(4, "select"),(5, "checkbox"),(6, "radio"),(7, "img"),(8, "file"),(9, "switch"),(10, "number"),(11, "array"),(12, "imgs"),(13, "foreignkey"),(14, "manytomany"),(15, "time"),)form_item_type = models.IntegerField(choices=FORM_ITEM_TYPE_LIST, verbose_name="表单类型", help_text="表单类型", default=0, blank=True)rule = models.JSONField(null=True, blank=True, verbose_name="校验规则", help_text="校验规则")placeholder = models.CharField(max_length=50, null=True, blank=True, verbose_name="提示信息", help_text="提示信息")setting = models.JSONField(null=True, blank=True, verbose_name="配置", help_text="配置")class Meta:db_table = table_prefix + "config"verbose_name = "系统配置表"verbose_name_plural = verbose_nameordering = ("sort",)unique_together = (("key", "parent_id"),)def __str__(self):return f"{self.title}"def save(self, force_insert=False, force_update=False, using=None, update_fields=None):super().save(force_insert, force_update, using, update_fields)# dispatch.refresh_system_config()  # 有更新则刷新系统配置def delete(self, using=None, keep_parents=False):res = super().delete(using, keep_parents)# dispatch.refresh_system_config()return resclass LoginLog(BaseModel):LOGIN_TYPE_CHOICES = ((1, "普通登录"), (2, "微信扫码登录"),)username = models.CharField(max_length=32, verbose_name="登录用户名", null=True, blank=True, help_text="登录用户名")ip = models.CharField(max_length=32, verbose_name="登录ip", null=True, blank=True, help_text="登录ip")agent = models.TextField(verbose_name="agent信息", null=True, blank=True, help_text="agent信息")browser = models.CharField(max_length=200, verbose_name="浏览器名", null=True, blank=True, help_text="浏览器名")os = models.CharField(max_length=200, verbose_name="操作系统", null=True, blank=True, help_text="操作系统")continent = models.CharField(max_length=50, verbose_name="州", null=True, blank=True, help_text="州")country = models.CharField(max_length=50, verbose_name="国家", null=True, blank=True, help_text="国家")province = models.CharField(max_length=50, verbose_name="省份", null=True, blank=True, help_text="省份")city = models.CharField(max_length=50, verbose_name="城市", null=True, blank=True, help_text="城市")district = models.CharField(max_length=50, verbose_name="县区", null=True, blank=True, help_text="县区")isp = models.CharField(max_length=50, verbose_name="运营商", null=True, blank=True, help_text="运营商")area_code = models.CharField(max_length=50, verbose_name="区域代码", null=True, blank=True, help_text="区域代码")country_english = models.CharField(max_length=50, verbose_name="英文全称", null=True, blank=True,help_text="英文全称")country_code = models.CharField(max_length=50, verbose_name="简称", null=True, blank=True, help_text="简称")longitude = models.CharField(max_length=50, verbose_name="经度", null=True, blank=True, help_text="经度")latitude = models.CharField(max_length=50, verbose_name="纬度", null=True, blank=True, help_text="纬度")login_type = models.IntegerField(default=1, choices=LOGIN_TYPE_CHOICES, verbose_name="登录类型",help_text="登录类型")class Meta:db_table = table_prefix + "system_login_log"verbose_name = "登录日志"verbose_name_plural = verbose_nameordering = ("-create_datetime",)class MessageCenter(BaseModel):title = models.CharField(max_length=100, verbose_name="标题", help_text="标题")content = models.TextField(verbose_name="内容", help_text="内容")target_type = models.IntegerField(default=0, verbose_name="目标类型", help_text="目标类型")target_user = models.ManyToManyField(to=Users, related_name='user', through='MessageCenterTargetUser',through_fields=('messagecenter', 'users'), blank=True, verbose_name="目标用户",help_text="目标用户")target_dept = models.ManyToManyField(to=Dept, blank=True, db_constraint=False,verbose_name="目标部门", help_text="目标部门")target_role = models.ManyToManyField(to=Role, blank=True, db_constraint=False,verbose_name="目标角色", help_text="目标角色")class Meta:db_table = table_prefix + "message_center"verbose_name = "消息中心"verbose_name_plural = verbose_nameordering = ("-create_datetime",)class MessageCenterTargetUser(BaseModel):users = models.ForeignKey(Users, related_name="target_user", on_delete=models.CASCADE, db_constraint=False,verbose_name="关联用户表", help_text="关联用户表")messagecenter = models.ForeignKey(MessageCenter, on_delete=models.CASCADE, db_constraint=False,verbose_name="关联消息中心表", help_text="关联消息中心表")is_read = models.BooleanField(default=False, blank=True, null=True, verbose_name="是否已读", help_text="是否已读")class Meta:db_table = table_prefix + "message_center_target_user"verbose_name = "消息中心目标用户表"verbose_name_plural = verbose_name

六、运行一下

1. 安装依赖环境pip install -r requirements.txt
2. 执行迁移命令:python manage.py makemigrationspython manage.py migrate
3、初始化数据
直接运行victor0802.sql就行,初始化数据,不用担心,如果存在table,删除重建,和版本一一应,后面添加了新的model
下载地址:【免费】smartwater项目数据库资源-CSDN文库
会更新sql,老的继续保留4. 启动项目python manage.py runserver 127.0.0.1:8000

5、http://127.0.0.1:8000/

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

深入理解 C 语言中的联合体

目录 引言 一、 联合体的定义与基本用法 1.联合体的定义 2.基本用法 二、 联合体与结构体的区别 1.结构体 2.联合体 3.对比 ​编辑三、联合体的优势 1. 节省内存 2. 提高效率 3. 代码简洁性 四、联合体的存储细节 1.内存对齐 2.大小计算 五、联合体的高级用法…

windows中node版本的切换(nvm管理工具),解决项目兼容问题 node版本管理、国内npm源镜像切换(保姆级教程,值得收藏)

前言 在工作中,我们可能同时在进行2个或者多个不同的项目开发,每个项目的需求不同,进而不同项目必须依赖不同版本的NodeJS运行环境,这种情况下,对于维护多个版本的node将会是一件非常麻烦的事情,nvm就是为…

JDK-java.nio包详解

JDK-java.nio包详解 概述 一直以来Java三件套(集合、io、多线程)都是最热门的Java基础技术点,我们要深入掌握好这三件套才能在日常开发中得心应手,之前有编写集合相关的文章,这里出一篇文章来梳理一下io相关的知识点。…

现代前端架构介绍(第三部分):深入了解状态管理层及其对前端App的影响

远离JavaScript疲劳和框架大战,了解真正重要的东西 在第二部分中,我们讨论了功能架构的三个层次。其中一个就是状态管理层,今天我们将对其进行更深入的探讨。下面是现代前端架构系列的第三部分和最后一部分介绍。 状态管理,你可能…

全球轻型汽车市场规划预测:2030年市场规模将接近2502亿元,未来六年CAGR为2.8%

一、引言 随着全球经济的发展和消费者出行需求的增加,轻型汽车作为汽车市场中的重要组成部分,其市场重要性日益凸显。本文旨在探索轻型汽车行业的发展趋势、潜在商机及其未来展望。 二、市场趋势 全球轻型汽车市场的增长主要受全球经济发展、消费者对出…

MySQL基础练习题19-查找拥有有效邮箱的用户

题目:查找具有有效电子邮件的用户 准备数据 分析数据 总结 题目:查找具有有效电子邮件的用户 一个有效的电子邮件具有前缀名称和域,其中: 前缀 名称是一个字符串,可以包含字母(大写或小写)&…

QtQuick Text-对齐方式

属性 Text项目 的horizontalAlignment和verticalAlignment分别用来设置文本在 Text项目区域中的水平、垂直对齐方式。 默认文本在左上方。 属性值有: horizontalAlignment Text.AlignLeftText.AlignRightText.AlignHCenterText.Justify verticalAlignment Text.…

js 前端 解析excel文件【.xlsx文件】信息内容

需求&#xff1a; 从excel文件中解析里面的内容 1、使用插件xlsx.full.min.js&#xff0c;地址&#xff1a;https://unpkg.com/xlsx/dist/xlsx.full.min.js实例&#xff1a; <script src"https://unpkg.com/xlsx/dist/xlsx.full.min.js"></script><i…

关于inet_addr()中的参数不能是 sring类型的 只能是 string类型变量.c_str()

源码展示&#xff1a; extern in_addr_t inet_addr (const char *__cp) __THROW inet_addr中的参数是const char *类型的 定义一个string 类型的ip 使用这个inet_addr()接口 local.sin_addr.s_addr inet_addr(ip_.c_str()); local.sin_addr.s_addr inet_addr(&ip_);…

(超全)Kubernetes 的核心组件解析

引言 在现代软件开发和运维的世界中&#xff0c;容器化技术已经成为一种标志性的解决方案&#xff0c;它为应用的构建、部署和管理提供了前所未有的灵活性和效率。然而&#xff0c;随着应用规模的扩大和复杂性的增加&#xff0c;单纯依靠容器本身来管理这些应用和服务已不再足够…

零基础入门转录组数据分析——机器学习算法之SVM-RFE(筛选特征基因)

零基础入门转录组数据分析——机器学习算法之SVM-RFE&#xff08;筛选特征基因&#xff09; 目录 零基础入门转录组数据分析——机器学习算法之SVM-RFE&#xff08;筛选特征基因&#xff09;1. SVM-RFE基础知识2. SVM-RFE&#xff08;Rstudio&#xff09;——代码实操2. 1 数据…

VS Code C/C++ MSVC编译器

官方教程 通过快捷方式打开VS Code是编译不了的,需要对tasks.json修改(Tasks: Configure default build task) 先创建tasks.json 复制这段配置到tasks.json,记得修改VsDevCmd.bat的路径 {"version": "2.0.0","windows": {"options"…

Gradle 统一管理依赖

BOM 介绍 BOM 是 Bill of Material 的简写&#xff0c;表示物料清单。BOM 使我们在使用 Maven 或 Gradle 构建项目时对于依赖版本的统一变得更加规范&#xff0c;升级依赖版本更容易。 比如我们使用 SpringBoot 和 SpringCloud 做项目时&#xff0c;可以使用他们发布的 BOM …

ARM 离线安装k8s + harbor私有镜像库(麒麟)

目录 1.1 K8S 服务集群安装部署 1.1.1 主机配置说明 1.1.2 主机名称、host配置 1.1.3 防火墙配置 1.1.4 关闭selinux 1.1.5 配置内核转发及网桥过滤 1.1.6 关闭SWAP分区 1.1.7 安装ipset及ipvsadm 1.1.8 时间同步(麒麟系统自带了chronyd) 1.1.9 docker安装 1.1.10 …

用户画像系列——Spark任务调优实践

在画像标签的加工和写入hbase中&#xff0c;我们采用了spark来快速进行处理和写入。但是在实际线上运行的过程中&#xff0c;仍然遇到了不少问题&#xff0c;下面来总结下遇到的一些问题 1.数据倾斜问题 其实spark 数据倾斜思路和hive、mapreduce 数据倾斜思路处理类似&…

ELK对业务日志进行收集

ELK对业务日志进行收集 下载httpd 进到文件设置收集httpd的文件进行 设置 编辑内容 用于收集日志的内容 将日志的内容发送到实例当中 input {file{path > /etc/httpd/logs/access_logtype > "access"start_position > "beginning"}file{path &g…

基于SpringCloud alibaba的流媒体视频点播平台

基于SpringCloud alibaba的流媒体视频点播平台 前言整体架构具体实现视频播放 总结 先把项目地址放这 》基于SpringCloud alibaba的流媒体视频点播平台《 然后咱们来看看这个项目是干啥的。 前言 今天和大家分享一个项目&#xff0c;基于SpringCloud alibaba的流媒体视频点…

嵌入式单片机中在线调试工具使用方法

大家好,相信很多小伙伴都听说过,或者用过SystemView这款工具。 它是一个可以在线调试嵌入式系统的工具,它可以分析RTOS有哪些中断、任务执行了,以及这些中断、任务执行的先后关系。 还可以查看一些内核对象持有和释放的时间点,比如信号量、互斥量、事件、消息队列等,这在…

紫辉创投开启Destiny of Gods首轮投资,伯乐与千里马的故事仍在继续

近日&#xff0c;上海紫辉创业投资有限公司&#xff08;以下简称“紫辉创投”&#xff09;宣布开启GameFi链游聚合平台Destiny of Gods首轮投资500,000美金&#xff0c;并与其达成全面战略及业务层合作&#xff0c;双方将协同布局链上生态&#xff0c;共同推动链游行业健康发展…

开发板与ubuntu不能ping通怎么办?

TOC 第一步&#xff1a;VMware 设置 打开 VMware Workstation Pro 里的 虚拟机 -> 设置 设置网络适配器为桥接模式。这里不要勾选“复制物理网络连接状态”。 因为电脑是 WiFi 上网&#xff0c;所以需要添加一个网络适配器并设置成 NAT 模式&#xff0c;供虚拟机上网。具…