Spa*_*ain 7 python django database-design
我的应用程序的数据库已填充并与外部数据源保持同步。我有一个抽象模型,我的 Django 2.2 应用程序的所有模型都来自该模型,定义如下:
class CommonModel(models.Model):
# Auto-generated by Django, but included in this example for clarity.
# id = models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')
ORIGIN_SOURCEA = '1'
ORIGIN_SOURCEB = '2'
ORIGIN_CHOICES = [
(ORIGIN_SOURCEA, 'Source A'),
(ORIGIN_SOURCEB, 'Source B'),
]
object_origin = models.IntegerField(choices=ORIGIN_CHOICES)
object_id = models.IntegerField()
class A(CommonModel):
some_stuff = models.CharField()
class B(CommonModel):
other_stuff = models.IntegerField()
to_a_fk = models.ForeignKey("myapp.A", on_delete=models.CASCADE)
class C(CommonModel):
more_stuff = models.CharField()
b_m2m = models.ManyToManyField("myapp.B")
Run Code Online (Sandbox Code Playgroud)
该object_id字段不能设置为唯一的,因为我在我的应用程序中使用的每个数据源可能都有一个带有object_id = 1. 因此需要通过场来追踪对象的起源object_origin。
不幸的是,Django 的 ORM 不支持多于一列的外键。
在将自动生成的主键保留在数据库 ( id) 中的同时,我想让我的外键和多对多关系发生在object_id和object_origin字段而不是主键上id。
我想过做这样的事情:
class CommonModel(models.Model):
# Auto-generated by Django, but included in this example for clarity.
# id = models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')
ORIGIN_SOURCEA = '1'
ORIGIN_SOURCEB = '2'
ORIGIN_CHOICES = [
(ORIGIN_SOURCEA, 'Source A'),
(ORIGIN_SOURCEB, 'Source B'),
]
object_origin = models.IntegerField(choices=ORIGIN_CHOICES)
object_id = models.IntegerField()
def _get_composed_object_origin_id(self):
return f"{self.object_origin}:{self.object_id}"
composed_object_origin_id = property(_get_composed_object_origin_id)
class A(CommonModel):
some_stuff = models.CharField()
class B(CommonModel):
other_stuff = models.IntegerField()
to_a_fk = models.ForeignKey("myapp.A", to_field="composed_object_origin_id", on_delete=models.CASCADE)
Run Code Online (Sandbox Code Playgroud)
但是 Django 抱怨它:
myapp.B.to_a_fk: (fields.E312) The to_field 'composed_object_origin_id' doesn't exist on the related model 'myapp.A'.
这听起来合法,Django 排除了to_field作为数据库字段的字段。但是没有必要向我添加一个新字段,CommonModel因为它composed_object_type_id是用两个不可为空的字段构建的......
您在另一个答案的评论中提到 object_id 不是唯一的,但它与 object_type 结合使用是唯一的,所以您可以unique_together在元类中使用 a吗?IE
class CommonModel(models.Model):
object_type = models.IntegerField()
object_id = models.IntegerField()
class Meta:
unique_together = (
("object_type", "object_id"),
)
Run Code Online (Sandbox Code Playgroud)