Django如何在同一模型中添加两个自动生成字段
Django模型实现position字段自动与自增ID同步
核心逻辑:Django自增主键ID是记录首次插入数据库时才由数据库生成的,无法在字段定义阶段直接绑定默认值为ID,通过重写模型内置save方法即可实现自动赋值。
操作步骤
- 修正字段定义笔误:原有代码中
model.为拼写错误,正确的模型字段引用前缀为models.;position字段使用PositiveIntegerField类型即可,无需提前设置默认值。 - 重写模型
save方法:首次调用父类save方法完成数据插入、拿到数据库生成的自增ID后,判断如果是新建记录(position未赋值),则将position赋值为当前实例的ID,指定更新字段再次保存即可,不会触发无限递归。 - 可选优化:如果业务中需要基于position做排序、高频筛选,可以给字段加上
db_index=True参数提升查询效率。
完整可运行代码
from django.db import models # 此处Vendor为业务已有模型,保持原有定义即可 class DeviceControl(models.Model): vendor_id = models.ForeignKey(Vendor, on_delete=models.CASCADE) id = models.AutoField(primary_key=True) name = models.CharField(max_length=100) description = models.CharField(max_length=1000) position = models.PositiveIntegerField(verbose_name="排序位置") def __str__(self): return self.name def save(self, *args, **kwargs): # 首次执行入库操作,获取数据库生成的自增ID super().save(*args, **kwargs) # 仅新建记录场景下同步ID值到position,避免重复更新 if not self.position: self.position = self.id # 仅更新position字段,减少不必要的全字段写入 super().save(update_fields=['position'])
注意事项
- 不要尝试在字段定义时写
position = models.PositiveIntegerField(default=id)这类代码:类定义阶段的id是字段对象而非实例的实际ID值,这类赋值逻辑完全不生效。 - 不要通过提前查询数据库自增序列值的方式预赋值position:高并发场景下会出现多个请求拿到相同序列值的问题,最终导致position和实际ID不匹配。
- 如果使用
bulk_create批量创建记录,模型重写的save方法不会被触发,需要在批量创建完成后遍历查询集手动批量同步position值。
内容的提问来源于stack exchange,提问作者Mukul
相关产品推荐
相关产品推荐

