Django设置managed=False时是否需在Meta中定义索引和唯一约束
核心结论先行
managed = False 仅会让Django跳过对目标表的表结构变更操作,不会影响索引、约束配置的其他用途,这类配置也并非仅用于迁移生成,是否添加可参考以下规则:
关于models.Index索引配置
- Django不会基于模型里的索引定义做查询优化,最终查询性能完全由MySQL层面的索引决定,Django生成SQL时不会因为你声明了索引就调整查询逻辑
- 非常推荐添加,核心作用是作为模型的元信息文档,后续维护代码的开发者不需要查询数据库建表语句,仅看模型就能明确哪些字段有索引,写查询时会主动考虑索引命中规则,避免写出全表扫描的慢查询
- 注意写法规范:
fields参数需要填Django模型的字段名,不是数据库列名,name参数建议和数据库里实际的索引名保持一致,方便对应排查问题
关于UniqueConstraint和字段unique参数配置
- 这类约束配置和索引不同,Django会在应用层做校验:调用模型
full_clean()方法、使用Django Admin、ModelForm提交数据时,Django会提前查询表中是否有重复值,不符合规则会直接抛出ValidationError,不需要请求走到数据库触发报错 - 即便不使用Admin、ModelForm,手动写业务逻辑时也可以主动调用
full_clean()做校验,比捕获数据库的IntegrityError友好很多,可以直接返回明确的字段错误提示给前端 - 写法注意:单字段唯一约束直接在字段上声明
unique=True即可,不需要额外在constraints里加UniqueConstraint,后者仅用于多字段联合唯一约束的场景
两个示例的最终推荐写法
示例1:Accounts模型
class Accounts(models.Model): account_number = models.IntegerField(db_column='ACCOUNT_NUMBER', primary_key=True) account_name = models.CharField(db_column='ACCOUNT_NAME', max_length=40, blank=True, null=True) payment_method = models.IntegerField(db_column='PAYMENT_METHOD', blank=True, null=True) flagged = models.BooleanField(db_column='FLAGGED', blank=True, null=True) class Meta: managed = False app_label = 'schoolsys' db_table = 'accounts' indexes = [ # 索引名和数据库实际名称保持一致,fields用模型字段名 models.Index(fields=['payment_method'], name='a_pm_ix') ]
示例2:SystemUsers模型
额外说明:你提供的建表语句里
USER_NAME字段已经有唯一索引,额外加的普通索引su_un_ix是冗余的,唯一索引本身已经支持普通查询的索引加速,重复加索引只会拖慢写入性能,因此模型中不需要额外声明普通索引
class SystemUsers(models.Model): user_id = models.IntegerField(db_column='USER_ID', primary_key=True) # 保留unique=True即可,不需要额外加UniqueConstraint user_name = models.CharField(db_column='USER_NAME', unique=True, max_length=20, blank=True, null=True) password = models.CharField(db_column='PASSWORD', max_length=40, blank=True, null=True) mgr_code = models.CharField(db_column='MGR_CODE', max_length=20, blank=True, null=True) is_admin = models.BooleanField(db_column='IS_ADMIN', blank=True, null=True) class Meta: managed = False app_label = 'schoolsys' db_table = 'system_users'
内容的提问来源于stack exchange,提问作者Kevin
相关产品推荐
相关产品推荐

