4

如何在模型字段中使用布尔选项来启用/禁用其他字段。如果布尔值为真/假,我希望它启用/禁用其他模型字段。有没有办法使用 django 模型/表单/小部件本地表达这些关系?我一直在编写自定义模板来模拟这些关系,但是如果没有特殊的模板,我无法找到一种在 django 中表示它们的好方法。

例如:

类PointInTime(模型。模型):
    is_absolute_time = models.BooleanField()
    absolute_time = models.DateTimeField()
    is_relative_time = models.BooleanField()
    days_before = models.IntegerField()

因此,如果 is_absolute_time 为 True,我希望 absolute_time 条目可在 GUI 中编辑,而 days_before 条目灰显且不可编辑。如果“is_relative_time”标志为 True,我希望 absolute_time 条目变灰,并且 days_before 值可编辑。因此 is_absolute_time 和 is_relative_time 将是 GUI 中同一组中的单选按钮,并且它们的两个对应字段仅在选择它们的单选按钮时才可编辑。这在自定义模板中很容易做到,但是有没有办法在 django 中使用模型/表单来本地显示这种关系?

4

2 回答 2

6

澄清“本机显示这种关系”的含义并清楚地考虑关注点分离会很有帮助。

如果您只想根据另一个字段的值“变灰”或禁用某个字段,这纯粹是一个演示/UI 问题,因此模板(和/或 Javascript)是处理它的合适位置。

如果您想验证提交的数据是否内部一致(即如果 is_absolute_time 为 True,则填写 absolute_time 等),这是一个表单验证问题。该逻辑的位置在您的 Form 或 ModelForm 对象的 clean() 方法中。

如果您想确保在没有内部一致的情况下不能将任何 PointInTime 模型保存到数据库中,那就是数据层问题。这样做的地方是在模型对象上的自定义 save() 方法中(Django 1.2 将包括更广泛的模型验证系统)。

所有这些选项都涉及编写命令式代码来完成您对这些特定字段的需要。您可能正在寻找一种在模型中以声明方式表示情况的方法,以便可以通用而不是专门编写上述所有三种情况的代码。没有内置的 Django 方法可以执行此操作,但您当然可以执行以下操作:

class PointInTime(models.Model):
    field_dependencies = {'is_absolute_time': 'absolute_time',
                          'is_relative_time': 'days_before'}
    ... fields here ...

然后,您的模型 save() 代码(或您的 Form clean() 代码或您的模板)可以使用此字典来确定应启用/禁用哪些字段,具体取决于哪个字段的值。但是,这种概括几乎不值得付出努力,除非您预计需要在许多不同的模型中做同样的事情。

最后,您可能需要考虑一些模式设计替代方案,以使您的数据层更好地规范化:

  • 如果只有两个有效状态(绝对和相对),请使用单个布尔字段而不是两个。然后你避免可能的不一致(如果两个布尔值都是假的,这意味着什么?还是真?)

  • 或者通过完全消除布尔值并仅在 absolute_time/days_before 中的一个或另一个中使用 Null 值来进一步简化。

  • 如果可能有两个以上的有效状态,请使用单个 IntegerField 或 CharField 进行选择,而不是使用两个布尔字段。与上述相同的原因,但可以容纳两个以上的选项。

  • 由于 RelativeTime 和 AbsoluteTime 似乎彼此不共享任何数据字段,因此请考虑将它们完全拆分为单独的模型。如果您有其他模型需要一个外键到另一个模型,您可以使用继承来建模(RelativeTime 和 AbsoluteTime 都继承自 PointInTime,其他模型具有指向 PointInTime 的外键)。

于 2009-02-03T18:29:14.320 回答
1

我不完全确定你在用这些对象做什么,但无论用户选择哪个,你都指向一个时间点。“5 天前”是“星期四”,反之亦然。

因此,除非日期随网站滚动(例如,“5 天前”的记录仍表示星期四、明天等),这肯定只是界面问题吗?如果是这种情况,我会坚持在您的模型中为日期使用单个值,并让表单和视图完成所有工作。

这解决了自动生成的管理方面的问题,因为您只需要处理一个字段,但除非您编写自己的表单小部件并覆盖模型的 ModelAdmin 类,否则它不会原生地让您在两者之间进行选择。

如果不是这种情况,请忽略此答案。

于 2009-02-03T16:29:48.287 回答