# +====================================================================== # | DjangoAdmin 企业数字化开发平台 [ 赋能开发者,助力企业发展 ] # +---------------------------------------------------------------------- # | Copyright (c) 2021-2026 小蚂蚁云团队 版权所有 # +---------------------------------------------------------------------- # | 开源协议: Apache-2.0 # | 重要声明: 未经书面许可,不得移除或修改本框架相关版权标识。 # +---------------------------------------------------------------------- # | 官方网站: https://www.djangoadmin.cn # +---------------------------------------------------------------------- # | 研发团队: 小蚂蚁云团队 荣誉出品 # +====================================================================== # | 版权和免责声明: # | 一、知识产权声明 # | 本团队对该软件框架产品(以下简称“本产品”)拥有完整知识产权,包括但不限于商标权、专利权、 # | 著作权、商业秘密等。前述权利均受中华人民共和国及相关国际法律法规保护。未经本团队书面授权, # | 任何个人或单位不得基于本产品本身申请任何形式的知识产权。 # | 二、使用限制与禁止条款 # | 您理解并同意,禁止将本产品用于以下任何行为: # | 1. 任何违反中华人民共和国法律法规的用途; # | 2. 任何侵害他人合法权益(包括但不限于人身权、财产权、知识产权等)的行为; # | 3. 任何危害国家安全、公共利益及社会道德风尚的行为。 # | 三、责任豁免 # | 因使用本产品而产生的任何损失或法律纠纷(包括但不限于直接损失、间接损失、附带损失、衍生损失 # | 以及因违约、侵权等引发的责任),本团队均不承担任何法律责任。若因违规使用本产品导致任何第三 # | 方提起索赔或行政机关进行调查,您应独立承担全部责任。 # | 四、违约与法律责任 # | 如发现任何违反本声明的行为,本团队有权: # | 1. 无条件配合公安机关及其他有权机关的调查取证工作; # | 2. 依法追究相关方的民事责任,并要求赔偿全部损失; # | 3. 保留进一步采取刑事控告等法律措施的权利。 # | 五、许可范围说明 # | 1、被授权方应视本产品源代码为核心机密信息,负有最高标准的保密与保管义务。禁止以任何形式(包 # | 括但不限于直接或间接的分享、复制、传播、分发、转售、出租、开源、反向工程、反编译、反汇编或通 # | 过网络服务提供给任何第三方)泄露、披露或处置源代码的全部或部分内容。任何未经授权的复制、使用、 # | 传播行为均构成对本团队知识产权的严重侵权,本团队有权依法追究其全部法律责任,并要求赔偿因此造 # | 成的一切经济损失及商誉损害。 # | 2、本产品仅限于公司或个人在法律允许范围内,用于内部且合规的软件产品研发。具体权利义务以《软件 # | 许可协议》附件为准。 # +====================================================================== from django.db import models from django.db.models.signals import class_prepared # 公共字段名称列表(按顺序) BASE_FIELD_NAMES = ['id', 'create_user', 'create_time', 'update_user', 'update_time', 'is_delete'] def _reorder_fields(sender, **kwargs): """ 信号处理函数:重排模型字段顺序,将公共字段移到最后 当 Django 准备好一个模型类时,会发送 class_prepared 信号。 我们在这里重新排列字段顺序。 """ # 只处理继承自 BaseModel 的模型(排除 BaseModel 自身) if not hasattr(sender, '_meta') or sender._meta.abstract: return # 检查是否有公共字段 has_base_fields = any(f.name in BASE_FIELD_NAMES for f in sender._meta.local_fields) if not has_base_fields: return # 分离公共字段和业务字段 base_fields = [] business_fields = [] for field in sender._meta.local_fields: if field.name in BASE_FIELD_NAMES: base_fields.append(field) else: business_fields.append(field) # 重新排列:业务字段在前,公共字段在后 sender._meta.local_fields = business_fields + base_fields # 注册信号处理器 class_prepared.connect(_reorder_fields) class BaseModel(models.Model): """ 基础模型抽象类 ============== 功能:提供所有模型的公共字段,如主键、创建人、创建时间等 特点:定义为抽象类,不会在数据库中创建对应的表 用途:被其他业务模型继承,实现字段复用 继承此基类的模型会自动拥有以下6个公共字段: - id: 自增主键 - create_user: 创建人 - create_time: 创建时间 - update_user: 更新人 - update_time: 更新时间 - is_delete: 逻辑删除标识 注意:公共字段会自动排列在业务字段之后,使数据库表结构更清晰 """ # ==================== 公共字段定义 ==================== # 主键ID字段 # 自增主键,每个模型的唯一标识符 id = models.AutoField( auto_created=True, # 自动创建主键字段 primary_key=True, # 设置为主键 serialize=False, # 不参与序列化(避免在API响应中暴露) verbose_name='主键ID', # 字段中文名称 db_comment='主键ID' # 数据库字段注释 ) # 创建人字段 # 记录数据由谁创建,通常关联用户表的用户名或ID # 例如:admin, zhangsan, system create_user = models.CharField( null=True, # 数据库允许为NULL max_length=50, # 最大长度50个字符 default=None, # 默认值为None db_default=None, # 数据库层默认值 verbose_name='创建人', # 字段中文名称 db_comment='创建人' # 数据库字段注释 ) # 创建时间字段 # 自动记录数据创建的时间戳 # auto_now_add: 仅在创建时自动设置当前时间,后续更新不会改变 create_time = models.DateTimeField( null=True, # 数据库允许为NULL auto_now_add=True, # 创建时自动设为当前时间 verbose_name="创建时间", # 字段中文名称 max_length=11, # 时间戳长度(DateTimeField实际上不需要max_length,这里可能是为了兼容性) db_comment='创建时间' # 数据库字段注释 ) # 更新人字段 # 记录数据最后由谁更新,通常关联用户表的用户名或ID # null=True: 允许数据库为NULL(新创建记录时可能没有更新人) update_user = models.CharField( null=True, # 数据库允许为NULL max_length=50, # 最大长度50个字符 default=None, # 默认值为None db_default=None, # 数据库层默认值 verbose_name='更新人', # 字段中文名称 db_comment='更新人' # 数据库字段注释 ) # 更新时间字段 # 自动记录数据最后更新的时间戳 # auto_now: 每次保存(更新)时自动设为当前时间 update_time = models.DateTimeField( null=True, # 数据库允许为NULL auto_now=True, # 每次保存时自动更新为当前时间 verbose_name="更新时间", # 字段中文名称 max_length=11, # 时间戳长度 db_comment='更新时间' # 数据库字段注释 ) # 逻辑删除标识 # 用于软删除,避免物理删除数据造成的数据丢失 # 0:正常(默认值)| 1:已删除 is_delete = models.BooleanField( default=0, # 默认为0,表示正常 db_default=0, # 数据库层默认值 verbose_name="逻辑删除", # 字段中文名称 db_comment='逻辑删除:0-正常 1-已删除' # 数据库字段注释 ) class Meta: """ 元数据配置 """ # 定义为抽象模型类 # abstract = True 表示这个模型是抽象的,不会在数据库中创建对应的表 # 子类模型会继承这些字段,并在各自对应的表中创建这些列 abstract = True """ BaseModel使用示例 ================= 1. 继承方式 class User(BaseModel): username = models.CharField(max_length=50) # ... 其他字段 这样User模型会自动拥有BaseModel中定义的所有字段: - id, create_user, create_time, update_user, update_time, is_delete 2. 查询示例 # 正常查询(排除已删除的数据) users = User.objects.filter(is_delete=0) # 包含已删除的数据 all_users = User.objects.all() # 只查询已删除的数据 deleted_users = User.objects.filter(is_delete=1) 3. 创建记录 user = User.objects.create( username='zhangsan', create_user='admin', # 需要手动设置创建人 # create_time会自动设置 # is_delete默认为0 ) 4. 更新记录 user = User.objects.get(id=1) user.username = 'lisi' user.update_user = 'admin' # 需要手动设置更新人 user.save() # update_time会自动更新 5. 软删除 user = User.objects.get(id=1) user.is_delete = 1 # 标记为已删除 user.update_user = 'admin' # 记录删除操作人 user.save() # 完成软删除 6. 物理删除(谨慎使用) user = User.objects.get(id=1) user.delete() # 真正的物理删除 注意事项: --------- 1. 所有继承BaseModel的表都会包含这些字段,查询时需要注意加上is_delete=0条件 2. create_user和update_user需要业务代码手动赋值 3. create_time和update_time由数据库自动管理 4. 建议在所有查询中都加上is_delete=0过滤,除非确实需要查询已删除数据 5. 可以在模型管理器中定义默认过滤器,自动过滤is_delete=0的数据 """