【问题标题】:Django unique together constrain with relationsDjango 独特的约束关系
【发布时间】:2018-10-28 10:10:14
【问题描述】:

我正在使用 Django 和 Django Rest Framework 编写一个 REST API。我目前正在编写模型。

我有一个学生模型、一个问题模型和一个答案模型。

class Question(models.Model):
    question_text = models.CharField()


class Answer(models.Model):
    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    answer_text = models.CharField()


class Student(models.Model):
    name = models.CharField()

每个问题学生应该能够选择一个且只能选择一个答案。 所以我正在考虑设计一个学生选择的答案模型——这样我就可以让学生通过关系来选择——就像这样:

class StudentPickedAnswer(models.Model):
    student = models.ForeignKey(Student, on_delete=models.CASCADE)
    answer = models.ForeignKey(Answer, on_delete=models.CASCADE)

我发现class Meta 有一个unique_together 约束。但在我看来,它无法指定关系。我需要这样的东西;

class Meta:
   unique_together = ('student', 'answer__question')

如何实现学生每个答案只能选择一个问题?还是挑选有关系的模型是一个糟糕的设计?

【问题讨论】:

  • unique_together 是在数据库级别指定的,这对关系一无所知,所以不,您不能“通过”外键查看。
  • @WillemVanOnsem 你知道我怎样才能做得更好吗?我正在考虑在 API 的序列化程序 validate 方法中强制执行它。

标签: django django-models django-2.1


【解决方案1】:

因为您提到学生需要为问题选择答案,所以我认为您需要为您的问题选项/选择建立一个模型。然后,您可以使用 (student, question) 上的 uniquetogether 为您的学生响应模型建模

class Question(models.Model):
    question_text = models.CharField()
    options = models.ManyToManyField(QuestionOption)

class QuestionOption(models.Model):
    option_text = models.CharField(max_length=255)

class Student(models.Model):
    name = models.CharField()

class StudentResponse(models.Model):
    student = models.ForeignKey(Student)
    question = models.ForeignKey(Question)
    response_option = models.ForeignKey(QuestionOption)

    class Meta:
        unique_together = ("student", "question")

如果每个问题都需要有独特的选择,则另一种方法。这类似于 Django 文档中的polls app tutorial

class Question(models.Model):
    question = models.CharField(...)

class QuestionOption(models.Model):
    question = models.ForeignKey("Question",related_name="qs_options")
    option = models.CharField(max_length=200)

    class Meta:
       # ensuring choices are not duplicated for a question.
       unique_together = ("question", "option")

【讨论】:

  • 感谢您的帮助!我也想过这个选项。我看到的唯一问题是没有办法强制执行该问题指向的问题实际上是当前选项的问题,是否存在?我的意思是可能有问题 A 和问题 B。在这个 StudentResponse 模型中,question 属性可能指向问题 A,而 response_option 指向问题 B 的选项。你认为有在这里执行完整性的方法?
  • @J.Hesters 使用我上面发布的方法,问题选项在不同问题之间共享,因此是多对多。但是,如果这不是必需的行为并且问题不共享选项,那么您可以将其作为 FK。但是,在这种情况下,很难通过模型获得每个学生每个问题只有一个答案的要求行为。然后你必须通过你的表单和验证来强制它。我已经编辑并在答案中包含了 FK 方法。
  • 感谢您的帮助,这绝对是一个进步!非常感谢。不幸的是,问题仍然存在,可以通过分配不属于相应questionresponse_option 来创建StudentResponse 损坏数据的这种方式。所以是的,我正在使用自定义权限和序列化程序的验证方法。
猜你喜欢
  • 2016-05-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-29
相关资源
最近更新 更多