我需要添加一个不是主键的autoinc字段。我正在将使用自动增量字段的非常大的生产数据库迁移到models.UUIDField
。我一直在进行分段迁移,现在我的所有关系都与两种字段类型都重复。我已准备好进行主键交换,但不幸的是,我仍然需要为旧客户端保留自动递增整数字段,因为它已被弃用。
由于django不允许我使用primary_key=False
定义自动文件(尽管db层完全支持),我正在寻找一个简单的解决方案。我的初始策略是将字段更改为models.BigIntegerField('GUID', db_index=True, null=True, unique=True)
,然后使用nextval('my_guid_seq'::regclass)
手动设置默认migrations.RunSQL
。到目前为止这么好,除了没有。事实证明,由于我的null=True
声明,ORM层的django正在接管并插入null
,这将不允许数据库层的默认值来完成它的工作。
核心开发人员很快拒绝这个请求,因为设计不好,我最绝对同意,但是有非常有效的用例,比如这个。 https://code.djangoproject.com/ticket/8576
我是一个非常弱的django开发者,所以我不想在ORM层进入杂草元编程。根据定义,这是一个黑客攻击,所以我正在寻找能够解决这个限制的最简单,最有创意的解决方案
答案 0 :(得分:3)
您可以继承AutoField
并覆盖_check_primary_key
方法。
from django.db.models.fields import AutoField
from django.db.models.fields import checks
class AutoFieldNonPrimary(AutoField):
def _check_primary_key(self):
if self.primary_key:
return [
checks.Error(
"AutoFieldNonPrimary must not set primary_key=True.",
obj=self,
id="fields.E100",
)
]
else:
return []
请参阅AutoField
源代码here
答案 1 :(得分:0)
我知道,将主键更改为UUID确实很麻烦,因此我想到的一种简单,更好的解决方案是添加另一个自动递增的整数字段。
这是我的解决方法:
class ModelName(models.Model):
auto_inc_id = models.IntegerField()
然后覆盖保存模型:
def save(self, *args, **kwargs):
self.object_list = ModelName.objects.order_by('auto_inc_id')
if len(self.sheets) is 0: # if there are no objects
self.auto_inc_id = 1
else:
self.auto_inc_id = self.object_list.last().auto_inc_id + 1
super(ModelName, self).save()
答案 2 :(得分:0)
无法将其格式化为评论,但修改@Abhimanyu 的答案以使保存方法更简洁(并且仅发出一个查询)。相同的模型属性:
class ModelName(models.Model):
auto_inc_id = models.IntegerField()
这是模型上的保存方法:
def save(self, *args, **kwargs):
self.auto_inc_id = ModelName.objects.all().count() + 1
super(ModelName, self).save()