as the question states, how do I do create a many-to-one relationship in django models?
正如问题所述,我如何在django模型中创建多对一关系?
Basically, I have two models: Article and Comic, I want to have one Comment model which will have a relationship with both Article and Comic, but not both. So if a Comment object has a relationship with an Article object, then it wont have a relationship with a Comic object.
基本上,我有两个模型:文章和漫画,我想有一个评论模型,它将与文章和漫画有关系,但不是两者。因此,如果Comment对象与Article对象有关系,那么它将不会与Comic对象建立关系。
I am currently doing it the following way, which does not work:
我目前正在以下列方式执行此操作,但这不起作用:
class Article(models.Model):
#other fields
class Comic(models.Model):
#other fields
class Comment(models.Model):
article = models.ForeignKey(Article)
comic = models.ForeignKey(Comic)
I would really appreciate some help.
我真的很感激一些帮助。
2 个解决方案
#1
1
This is tricky. I think there are a couple ways you could model this.
这很棘手。我认为有几种方法可以对此进行建模。
Using your current way you could enforce your uniqueness constraint in the application.
使用当前的方式,您可以在应用程序中强制执行唯一性约束。
class Comment(models.Model):
article = models.ForeignKey(Article)
comic = models.ForeignKey(Comic)
def save(self, *args, **kwargs):
# assert that there is either comic OR article but not both
super(Comment, self).save(*args, **kwargs)
with this way, what happens if you add another model that you want Comment
to reference?? You will have to manually add the conditional for the new type in your save method and perform a migration.
通过这种方式,如果你添加另一个你想要引用的模型会发生什么?您必须在save方法中手动添加新类型的条件并执行迁移。
Django provides GenericForeignKey field that would allow you to reference any model from Comment
. https://docs.djangoproject.com/en/1.8/ref/contrib/contenttypes/#generic-relations
Django提供了GenericForeignKey字段,允许您从Comment引用任何模型。 https://docs.djangoproject.com/en/1.8/ref/contrib/contenttypes/#generic-relations
This would allow you to create a generic reference from Comment
to either Article or Comic, and since it is only one field, would by default be mutually exclusive. I find querying and using GenericeForeignKey
s awkward; but they are still an option, that might work fine for your use case.
这将允许您创建从Comment到Article或Comic的通用引用,并且由于它只是一个字段,因此默认情况下是互斥的。我发现查询和使用GenericeForeignKeys很尴尬;但它们仍然是一个选项,可能适用于您的用例。
Another powerful option, (my favorite) could be to create a polymorphic model, which would also be mutually exclusive.
另一个强大的选择(我最喜欢的)可能是创建一个多态模型,它也是互斥的。
Each Comment
could reference a generic Piece of Content
, using model inheritance. (I did not test the following, so it will probably not work as copied/pasted)
每个Comment都可以使用模型继承来引用通用的内容。 (我没有测试以下内容,因此它可能无法复制/粘贴)
class Content(models.Model):
objects = InheritanceManager()
# shared content fields could be stored in this model
class Article(Content):
# article specific fields
class Comic(Content):
# comic specific fields
class Comment(models.Model):
content = models.OneToOneField(Content)
This is a powerful way to model the relationship of Comment
to any Content
. This DOES add additional query overhead, and should warrant an audit for your use case.
这是对Comment与任何Content的关系进行建模的强大方法。这会增加额外的查询开销,并应保证对您的用例进行审核。
InheritanceManager
is a utility provided by django-model-utils package, and is pretty lightweight. I have used in in production environment and it is performant, as long as you understand the additional query overheard involved with modeling your data using it. https://django-model-utils.readthedocs.org/en/latest/managers.html#inheritancemanager
InheritanceManager是一个由django-model-utils包提供的实用程序,非常轻量级。我已经在生产环境中使用过,只要你理解了使用它来建模数据所涉及的额外查询,它就是高效的。 https://django-model-utils.readthedocs.org/en/latest/managers.html#inheritancemanager
The query overhead is explained in the documentation.
查询开销在文档中进行了解释。
If you think you will add additional Content
subclasses in the future this could be a scalable way to model your relationship, and provides more flexibility in filtering then GenericForeignKey
s.
如果您认为将来会添加其他内容子类,这可能是一种可扩展的方式来建模您的关系,并提供更灵活的过滤GenericForeignKeys。
#2
0
Well, you can add another field to you Comment model. Like
好吧,你可以为你添加另一个字段评论模型。喜欢
class Comment(models.Model):
article = models.ForeignKey(Article, null = True)
comic = models.ForeignKey(Comic, null = True)
assigned = models.BooleanField(initial=False)
Once a comment object is created, put either article or comic to point at another object and make assigned = True.
创建注释对象后,将文章或漫画指向另一个对象并使assign = True。
#1
1
This is tricky. I think there are a couple ways you could model this.
这很棘手。我认为有几种方法可以对此进行建模。
Using your current way you could enforce your uniqueness constraint in the application.
使用当前的方式,您可以在应用程序中强制执行唯一性约束。
class Comment(models.Model):
article = models.ForeignKey(Article)
comic = models.ForeignKey(Comic)
def save(self, *args, **kwargs):
# assert that there is either comic OR article but not both
super(Comment, self).save(*args, **kwargs)
with this way, what happens if you add another model that you want Comment
to reference?? You will have to manually add the conditional for the new type in your save method and perform a migration.
通过这种方式,如果你添加另一个你想要引用的模型会发生什么?您必须在save方法中手动添加新类型的条件并执行迁移。
Django provides GenericForeignKey field that would allow you to reference any model from Comment
. https://docs.djangoproject.com/en/1.8/ref/contrib/contenttypes/#generic-relations
Django提供了GenericForeignKey字段,允许您从Comment引用任何模型。 https://docs.djangoproject.com/en/1.8/ref/contrib/contenttypes/#generic-relations
This would allow you to create a generic reference from Comment
to either Article or Comic, and since it is only one field, would by default be mutually exclusive. I find querying and using GenericeForeignKey
s awkward; but they are still an option, that might work fine for your use case.
这将允许您创建从Comment到Article或Comic的通用引用,并且由于它只是一个字段,因此默认情况下是互斥的。我发现查询和使用GenericeForeignKeys很尴尬;但它们仍然是一个选项,可能适用于您的用例。
Another powerful option, (my favorite) could be to create a polymorphic model, which would also be mutually exclusive.
另一个强大的选择(我最喜欢的)可能是创建一个多态模型,它也是互斥的。
Each Comment
could reference a generic Piece of Content
, using model inheritance. (I did not test the following, so it will probably not work as copied/pasted)
每个Comment都可以使用模型继承来引用通用的内容。 (我没有测试以下内容,因此它可能无法复制/粘贴)
class Content(models.Model):
objects = InheritanceManager()
# shared content fields could be stored in this model
class Article(Content):
# article specific fields
class Comic(Content):
# comic specific fields
class Comment(models.Model):
content = models.OneToOneField(Content)
This is a powerful way to model the relationship of Comment
to any Content
. This DOES add additional query overhead, and should warrant an audit for your use case.
这是对Comment与任何Content的关系进行建模的强大方法。这会增加额外的查询开销,并应保证对您的用例进行审核。
InheritanceManager
is a utility provided by django-model-utils package, and is pretty lightweight. I have used in in production environment and it is performant, as long as you understand the additional query overheard involved with modeling your data using it. https://django-model-utils.readthedocs.org/en/latest/managers.html#inheritancemanager
InheritanceManager是一个由django-model-utils包提供的实用程序,非常轻量级。我已经在生产环境中使用过,只要你理解了使用它来建模数据所涉及的额外查询,它就是高效的。 https://django-model-utils.readthedocs.org/en/latest/managers.html#inheritancemanager
The query overhead is explained in the documentation.
查询开销在文档中进行了解释。
If you think you will add additional Content
subclasses in the future this could be a scalable way to model your relationship, and provides more flexibility in filtering then GenericForeignKey
s.
如果您认为将来会添加其他内容子类,这可能是一种可扩展的方式来建模您的关系,并提供更灵活的过滤GenericForeignKeys。
#2
0
Well, you can add another field to you Comment model. Like
好吧,你可以为你添加另一个字段评论模型。喜欢
class Comment(models.Model):
article = models.ForeignKey(Article, null = True)
comic = models.ForeignKey(Comic, null = True)
assigned = models.BooleanField(initial=False)
Once a comment object is created, put either article or comic to point at another object and make assigned = True.
创建注释对象后,将文章或漫画指向另一个对象并使assign = True。