我正在创建一个新的Django(1.7)模型:
class MyModel(models.Model):
field1 = models.ForeignKey('OtherModel')
field2 = models.ForeignKey('AnotherModel', null=True)
field3 = models.PositiveSmallIntegerField(db_index=True, null=True)
other_field1 = models.FloatField(default=0, db_index=True)
class Meta:
unique_together = (('field1', 'field2', 'field3'), )
理想情况下,我希望它具有元组(field1
,field2
,field3
)作为主键,但是将that's not possible at the moment作为主键。
因此,取而代之的是,我自动创建并递增了id
列,这是Django所必需的,但对我的其余代码完全没用。。
问题是,我希望能够经常(几乎连续)删除和重新创建此模型的实例。
出于性能方面的考虑,我想避免使用create_or_update
方法,因为删除和创建的速度比我测试过的要快得多(使用create_or_update
方法的速度为18op / s,72op / s使用“全部删除并创建”方法,我希望这些数字在我们的生产服务器上会更高)。
但是我担心也很快达到自动递增上限(似乎大约一年)。
我想象的其他可能性:
BigAutoField
直到Django 1.10才可用)UUIDField
直到Django 1.8才可用)CharField
主键,类似于"{self.field1.pk}/{self.field2.pk}/{self.field3}"
,但我什至不知道Django是否可以根据实例本身来处理主键生成器(虽然优点是即使在null
和field2
上使用field3
值也可以确保唯一性) 您的建议是什么(除了升级到较新版本的Django,我知道我来晚了...)?您是否认为我正在寻找太多优化?
堆栈:
答案 0 :(得分:1)
如果您喜欢冒险,可以尝试将id
列变成没有默认值的可空整数列。
注意:这将破坏Model API的某些部分,管理员,并且很可能会引起各种无法预料的麻烦,但是根据您的用例,它可能会做您想要的事情。我并不是说这是个好主意,我只是向您展示这个选项。
话虽如此,这是必要的迁移:
migrations.RunSQL([
"ALTER TABLE myapp_mymodel DROP CONSTRAINT myapp_mymodel_pkey",
"ALTER TABLE myapp_mymodel ALTER COLUMN id drop default",
"ALTER TABLE myapp_mymodel ALTER COLUMN id drop not null"]
),
您仍然可以创建新对象并获取现有对象,但是不能直接保存或删除对象:
>>> m = MyModel.objects.create(field1=1, field2=2, field3=3)
>>> m
<MyModel: MyModel object (None)>
>>> m.delete()
Traceback (most recent call last):
File "<console>", line 1, in <module>
File ".../lib/python3.6/site-packages/django/db/models/base.py", line 886, in delete
(self._meta.object_name, self._meta.pk.attname)
AssertionError: MyModel object can't be deleted because its id attribute is set to None.
但是,您可以使用.filter(...).delete()
和.filter(...).update(...)
:
>>> MyModel.objects.filter(field1=1, field2=2, field3=3).update(field3=4)
1
>>> MyModel.objects.filter(field1=1, field2=2, field3=4).delete()
(1, {'myapp.MyModel': 1})
我用来测试此行为的MyModel
具有三个PositiveSmallIntegerFields,而不是ForeignKeys,但这没有什么区别:
class MyModel(models.Model):
field1 = models.PositiveSmallIntegerField()
field2 = models.PositiveSmallIntegerField()
field3 = models.PositiveSmallIntegerField(db_index=True, null=True)
other_field1 = models.FloatField(default=0, db_index=True)
class Meta:
unique_together = (('field1', 'field2', 'field3'), )