首页 > 解决方案 > 外键和预定义值的组合作为 Django 模型字段的选择

问题描述

其中一个模型中的ForeignKey字段存储对另一个模型的引用,其中存储了不同版本的terms and conditions文档。

class Venue(models.Model):
    tc = models.ForeignKey(
    'my_app.TC',
    on_delete=models.CASCADE,
    help_text=_('Version of tc used by this venue')
)

这样,每个人都可以选择适合他们需要Venue的版本之一。tc

表中的记录TC经常添加,因此如果给定Venue想要使用最新版本的文档,则需要手动更新它django admin。这是一个考虑不周的解决方案,因为数据库中有数十条Venue记录,它们都有不同的tc使用方法:


需要实现的目标是为每个提供 2 个额外的默认选项Venue

1. ---- (blank: venue does not use any `tc`)
2. Latest (venue automatically uses latest version of `tc` available`

以及未指定数量的可用tc选项(例如TC模型的外键)

1. v1.0.0
2. v2.1.0
3. ...

在这种情况下Latest不是与TC对象的关系。tc因此,字段 in的选择列表django admin可能如下所示:

- ---- (blank)
- Latest (literally option is named this was, not latest added `tc` object`)
- v1.0.0
- v2.1.0
- ... (other `tc` objects follow down the list)

Venue选择选项的方式Latest将自动使用最新添加的版本TC(对此的处理超出了此问题的范围)。Venue选择了某些特定版本的TC将保留它,直到有人手动更改它。

有没有办法为ForeignKey字段提供默认值或使用外键作为choicesfor中的选项CharField

标签: djangodjango-models

解决方案


您可以尝试创建一个自定义字段,但我认为这太麻烦了。解决此问题的最佳方法是创建两个字段,一个 ForeignKey 和一个简单的标志,用于确定是否获取最新的 tc。然后,您可以定义一个自定义属性来获取正确的 TC。

要允许空白 ForeignKey 字段,只需将nulland设置blank为 True。

像这样的东西:

class Venue(models.Model):

     _tc = models.ForeignKey(
          'my_app.TC',
          on_delete=models.CASCADE,
          help_text=_('Version of tc used by this venue'),
          null = True, blank = True
      )

     use_latest_tc = models.BooleanField(default=False)

     @property
     def tc(self):
         if self.use_latest_tc:
              return TC.objects.latest()
         return self._tc

根据您更改此值的位置,您可以为您的表单编写自定义 JS,在启用使用 latest 时隐藏 ForeignKeyField。

以下内容未经测试,但可能有效。通过为 tc 创建一个 setter,您也许可以创建一个带有字段 'tc' 和可能值的表单:

@tc.setter
def tc(self, value):
    if value == 'latest':
        self.use_latest_tc = True
        self._tc = True
    else:
        self.use_latest_tc = False
        self._tc = value

推荐阅读