ForeignKey的优点和缺点是什么,而不是ManyToManyField

时间:2016-06-08 08:41:09

标签: django model foreign-keys many-to-many

在django tutorial中,它建模了一个民意调查结构:

from django.db import models

class Question(models.Model):
    question_text = models.CharField(max_length=200)
    pub_date = models.DateTimeField('date published')


class Choice(models.Model):
    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    choice_text = models.CharField(max_length=200)
    votes = models.IntegerField(default=0)

但我总是想知道为什么他们不像ManyToMany关系那样实现:

from django.db import models

class Question(models.Model):
    question_text = models.CharField(max_length=200)
    pub_date = models.DateTimeField('date published')
    choices = models.ManyToManyField(Choice)

class Choice(models.Model):
    choice_text = models.CharField(max_length=200)
    votes = models.IntegerField(default=0)

有什么优点和缺点?

1 个答案:

答案 0 :(得分:1)

我确定他们在教程中使用了ForeignKey(一对多)关系,因为他们试图让示例尽可能简单,只有两个模型:Question和{{1} }。请注意,Choicevotes模型的字段,这样可以非常简单地显示投票结果。

如果您正在进行投票,您对每个问题都有相同的选择(非常同意,有些同意等),那么ManyToMany关系可能是合适的。但这会让事情变得更复杂。您建议的ManyToMany关系模型是:

Choice

但如果没有一些更改,这将无法正常工作。from django.db import models class Question(models.Model): question_text = models.CharField(max_length=200) pub_date = models.DateTimeField('date published') choices = models.ManyToManyField(Choice) class Choice(models.Model): choice_text = models.CharField(max_length=200) votes = models.IntegerField(default=0) 仍然是votes表的字段,但现在每个选项都适用于许多问题。你可以看到强烈同意的选择获得了38票,但你无法分辨选民同意的问题。为了能够正确制表投票,您必须执行类似

的操作
Choice

现在,您可以准确地列出每个问题选择组合投票的人数,但它更复杂,不太适合入门教程。

使用你提出的ManyToMany模型,Django会在幕后自动创建from django.db import models class Question(models.Model): question_text = models.CharField(max_length=200) pub_date = models.DateTimeField('date published') choices = models.ManyToManyField('Choice', through='QuestionChoices') class Choice(models.Model): choice_text = models.CharField(max_length=200) class QuestionChoices(models.Model): question = models.ForeignKey(Question, on_delete=models.CASCADE) choice = models.ForeignKey(Choice, on_delete=models.CASCADE) votes = models.IntegerField(default=0) 模型,但是为了将QuestionChoices字段附加到它上,你必须自己明确地做。

如果您的关系可以建模为OneToMany或ManyToMany,则优缺点取决于您的特定应用程序。通常,您希望使用最准确反映现实情况的模型。但您还必须考虑如何更新和汇总数据,并尝试达成最佳折衷方案。根据我的经验,很多情况下选择都很困难。