我正在设计一个新的Django应用程序,由于有多种可能性,我不确定哪一种是最好的,因此我想听取意见,并希望改进到目前为止所得到的结果。
这个问题 接近但不完全。 这篇文章 涉及到扁平/嵌套的主题,很有帮助,但仍然没有回答我的问题。还有许多其他关于相同主题的文章,但没有一个告诉我我想知道的东西。
背景
这些模型都具有各自独特的属性和一些共享的属性,并且我需要在另一个模型中引用它们,最理想的情况是有一个单一的入口,而不是为每个可能的模型都有一个字段。
我希望能够使用复杂的Django ORM查询涉及基类并在需要时通过子类进行过滤。例如 Event.objects.all()
返回所有事件。我知道 Django模型工具继承管理器 并打算在可能的情况下使用它。
此外,我将使用django admin创建和管理对象,因此易于集成是必须的。我希望能够直接创建新的SubEvent,而无需先创建Event实例。
示例
为了说明,假设我有以下用于应用程序A
的模型。
class Event(models.Model):
commom_field = models.BooleanField()
class Meta:
abstract = True
class SubEventA(Event):
email = models.EmailField(unique=True)
class SubEventB(Event):
title = models.TextField()
class SubEventC(Event):
number = models.IntegerField(default=10)
# and so on
我需要翻译关于IT技术的内容。以下是需要翻译的内容:
还有一个应用程序B
,我希望能够引用任何类型的事件,例如:
class OtherModel(models.Model):
event = models.ForeignKey('A.Event')
# This won't work, because `A.Event` is abstract.
可能的解决方案
Use a GenericForeignKey.
# B.models.py class OtherModel(models.Model): content_type = models.ForeignKey(ContentType) object_id = models.PositiveIntegerField() event = GenericForeignKey('content_type', 'object_id')
What I don't like about this is that I'll lose the querying capabilities Django ORM has, and I might need to do additional fiddling to get it working on admin. Not sure, never dealt with this before
Flatten
Event
I can bring it all up to the base class and have flags or checks outside the model definition, something like:
class Event(models.Model): commom_field = models.BooleanField() email = models.EmailField(blank=True) title = models.TextField(blank=True) number = models.IntegerField(default=10)
This might seem like the best idea at first, but of course there are other kind of fields, and that forces me to allow nulls/blanks for most of them (like the email field), losing the db level integrity check.
OneToOne relationships
Rather than abstract like on 1 or flatten on 2 it is possible to have a db table for each, where the models will look like:
class Event(models.Model): commom_field = models.BooleanField() class SubEventA(models.Model): event = models.OneToOneField(Event) email = models.EmailField(unique=True) class SubEventB(models.Model): event = models.OneToOneField(Event) title = models.TextField(blank=True) class SubEventC(models.Model): event = models.OneToOneField(Event) number = models.IntegerField(default=10)
So far it solved the two initial problems, but now when I get to the admin interface, I'll have to customize each form to create the base
Event
before saving aSubEvent
instance.
问题
有更好的方法吗?
我提出的任何选择都可以在任何方向上进行改进吗(ORM查询,DB约束,管理界面)?