3

我正在制作一个 django 应用程序,但我遇到了一个问题。我正在尝试定义一个模型,其中一个ForeignKey将依赖于另一个模型ForeignKey

描述部分

我的申请是关于做出选择的。

因此,假设您decision要制作 a,adecision有多个choices,并且 achoice有 a status(由于其他约束)。

Astatus可以用于多个choices,但 astatus只能与一个相关,即与链接到decision的同一个choice

数据库架构

它不是固定的,如果需要可能会更改:

,____________,                  ,____________,
|            | 1, n        1, 1 |            |
|  Decision  |------------------|   Status   |
|____________|                  |____________|
      |                                |
      | 1, n                           | 1, n
      |                                |
      | 1, 1                           |
,_____|______,                         |
|            | 1, 1                    |
|   Choice   |-------------------------'
|____________|

代码

这是我当前的(简化的)(不工作的)代码:

class Decision (models.Model):
    name = models.CharField (max_length = 63)

class Status (models.Model):
    value = models.CharField (max_length = 63)
    decision = models.ForeignKey (Decision)

class Choice (models.Model):
    name = models.CharField (max_length = 63)

    decision = models.ForeignKey (Decision)
    status = models.ForeignKey (Status, limit_choices_to = {'decision' : decision})

这里的重要部分是limit_choices_to = {'decision' : decision}.

额外信息

我发现了另一个 SO 问题(在 django 中,如何根据同一模型中的另一个字段限制对外国字段的选择?)处理相同的问题,但问题已经过时了,最好的答案是依赖外部应用程序(django-smart-selects)。

我宁愿不必使用外部的东西,而且我不明白为什么仅使用 Django 无法解决像 3 表关系这样简单的问题!

如果有人有任何解决方案或任何建议,请告诉我。

4

4 回答 4

3

您要问的是不可能的,至少不在您设置的范围内(没有表格,没有外部库)。您的模型的status字段Choice是外键,两个表之间的关系......它本身不处理过滤,简单地说 - 它没有这个功能。这不是django的事情,这是数据库的事情。Django ORM 并不像你想象的那样远离数据库,它很棒,但并不神奇。

一些可用的解决方案是:

  • 通过过滤查询集在 FormField 级别执行此操作
  • 使用类似django-smart-selects 的东西(这就是上面的)
  • 覆盖save您的模型,在此处添加检查,如果失败则抛出错误
  • 创建一个属性并在status设置时对其进行验证检查

如果您使用FormField方法和覆盖save,您将受益于知道Choice无法保存它,它违反了这个约束,无论是从用户端(填写表格)还是后端(调用.save()的代码一个Choice实例。

于 2013-07-08T12:55:06.907 回答
1

我认为您在这里需要的是一个through模型,如下所示:

class Choice (models.Model):
    name = models.CharField (max_length = 63)
    status = models.ForeignKey(Status)
    decision = models.ForeignKey(Decision)

class Status(Models.Model):
    name = models.CharField(max_length=20)

class Decision(models.Model):
    name = models.CharField(max_length = 63)
    choices = models.ManyToManyField(Status, through = "Choice")    

这样一来,每一个决定都有很多选择,每一个选择只有一个状态。您可以进行如下查询: my_decision.choices.all()my_status.decision_set.all()

我建议您查看文档以获取有关如何通过模型使用的示例

于 2013-07-08T22:46:10.070 回答
1

我对 Django 不熟悉,但如果您试图解决问题的“与选择相关联的同一个”部分,这就是在数据库级别完成的方法:

在此处输入图像描述

请注意识别关系的用法,因此它DecisionId被迁移到两个“分支”并在“底部”合并。所以如果一个ChoiceStatus,它们都必须链接到同一个Decision

于 2013-07-07T16:01:03.300 回答
0

在以下语句decision中既不是可调用对象也不是models.Q对象:

status = models.ForeignKey (Status, limit_choices_to = {'decision' : decision})

这是一种表示数据的方法:

class Decision(models.Model):
    ...

# a status is relevant for only one decision
# there may be more than one Status per Decision.
class Status(Models.Model):
    decision = models.ForeignKey(Decision)

# each choice is linked to one decision and has a status.
class Choice (models.Model):
    status = models.ForeignKey(Status)
    # if status is mandatory, then you can get the decision
    # from status.decision. per se, this fk could be optional.
    decision = models.ForeignKey(Decision)

这是另一个:

class Decision(models.Model):
    ...

# a decision has multiple choices
# a choice pertains to only one decision
class Choice (models.Model):
    decision = models.ForeignKey(Decision)

# each status is relevant to one decision
# and may encompass multiple choices.
class Status(Models.Model):
    decision = models.ForeignKey(Decision)
    # problem with this representation is that this allows for
    # a choice to be linked to multiple statuses.
    # this happens when using M2M instead of ForeignKey.
    choices = models.ManyToManyField(Choice)
于 2013-07-09T09:52:58.150 回答