python - Django - 使用属性作为外键
问题描述
我的应用程序的数据库已填充并与外部数据源保持同步。我有一个抽象模型,我的 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")
该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)
但是 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"),
)
推荐阅读
- cron - 自动更新后 VestaCP Cronjob 不工作
- spacy - EntityLinker Spacy 返回的实体不正确
- amazon-web-services - 无权执行:资源上的 sts:TagSession:***
- java - 无法为在客户端加载的网站获取 html
- highcharts - Android / iOS 的 High Charts 中是否有序数设置?
- r - 在ggplot2中更改点图的y轴顺序
- firebase - 苹果的uid过期后会改吗?
- flutter - [Flutter]:未处理的异常:MissingPluginException(在通道 image_gallery_saver 上找不到方法 saveImageToGallery 的实现)
- python - Python:将数据框中的数组转换为多行
- ktor - Ktor 为作为 cookie 一部分的特殊符号添加特殊值