ForeignKey 而不是 ManyToManyField 的优缺点是什么
What's the pros and cons of ForeignKey instead of ManyToManyField
在 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)
优缺点是什么?
我确定他们在教程中使用了外键(一对多)关系,因为他们试图让示例尽可能简单,只有两个模型:Question
和 Choice
.请注意,votes
是 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
仍然是 Choice
table 的一个字段,但现在每个选择都适用于许多问题。您将能够看到“强烈同意”选项获得了 38 票,但您无法判断选民同意哪些问题。为了能够正确地列出选票,你必须做类似
的事情
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)
现在您可以准确地列出有多少人为每个问题-选择组合投票,但它更复杂并且不太适合table入门教程。
对于您提出的 ManyToMany 模型,Django 会在幕后自动创建 QuestionChoices
模型,但为了将 votes
字段附加到它,您必须自己明确地执行此操作。
如果您的关系可以建模为 OneToMany 或 ManyToMany,则优缺点取决于您的特定应用程序。通常,您希望使用最准确地反映现实生活情况的模型。但你也得考虑你需要如何更新和汇总数据,并尝试达成最佳折衷。根据我的经验,选择困难的情况并不多。
在 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)
优缺点是什么?
我确定他们在教程中使用了外键(一对多)关系,因为他们试图让示例尽可能简单,只有两个模型:Question
和 Choice
.请注意,votes
是 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
仍然是 Choice
table 的一个字段,但现在每个选择都适用于许多问题。您将能够看到“强烈同意”选项获得了 38 票,但您无法判断选民同意哪些问题。为了能够正确地列出选票,你必须做类似
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)
现在您可以准确地列出有多少人为每个问题-选择组合投票,但它更复杂并且不太适合table入门教程。
对于您提出的 ManyToMany 模型,Django 会在幕后自动创建 QuestionChoices
模型,但为了将 votes
字段附加到它,您必须自己明确地执行此操作。
如果您的关系可以建模为 OneToMany 或 ManyToMany,则优缺点取决于您的特定应用程序。通常,您希望使用最准确地反映现实生活情况的模型。但你也得考虑你需要如何更新和汇总数据,并尝试达成最佳折衷。根据我的经验,选择困难的情况并不多。