如何在模型字段中使用布尔选项来启用/禁用其他字段。如果布尔值为true / false,我希望它启用/禁用其他模型字段。有没有办法使用django models / forms / widgets本地表达这些关系?我一直在编写自定义模板来模拟这些关系,但是如果没有特殊的模板,就无法找到在django中表示它们的好方法。
例如:
class PointInTime(models.Model): is_absolute_time = models.BooleanField() absolute_time = models.DateTimeField() is_relative_time = models.BooleanField() days_before = models.IntegerField()
因此,如果is_absolute_time为True,我希望在GUI中可以编辑absolute_time条目,并且days_before条目将变灰并且不可编辑。如果'is_relative_time'标志为True,我希望absolute_time条目显示为灰色,并且days_before值可以编辑。因此,is_absolute_time和is_relative_time将是GUI中同一组中的单选按钮,并且只有在选中单选按钮时,它们的两个相应字段才可编辑。这在定制模板中很容易做到,但是有没有办法在django中使用模型/表单本地显示这种关系?
答案 0 :(得分:6)
通过“本地展示这种关系”澄清你的意思会很有帮助,并清楚地思考关注点的分离。
如果您想要的是“灰显”或根据另一个字段的值禁用某个字段,这纯粹是一个演示/ UI问题,因此模板(和/或Javascript)是适当的处理位置它
如果要验证提交的数据是否内部一致(即如果is_absolute_time为True,则填写absolute_time等),这是表单验证问题。该逻辑的位置在Form或ModelForm对象的clean()方法中。
如果您想确保在没有内部一致性的情况下不能将PointInTime模型保存到数据库,那么这就是数据层问题。它的位置在模型对象的自定义save()方法中(Django 1.2将包含more extensive model validation system)。
所有这些选项都涉及编写命令式代码,以便根据这些特定字段执行所需操作。您可能正在寻找一种在模型中以声明方式表示情况的方法,以便上述所有三种情况中的代码都可以一般而不是具体地编写。没有内置的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似乎没有彼此共享任何数据字段,因此请考虑将它们完全拆分为单独的模型。如果你有其他模型需要一个ForeignKey到一个或另一个,你可以使用继承对其进行建模(RelativeTime和AbsoluteTime都继承自PointInTime,其他模型有ForeignKeys到PointInTime)。
答案 1 :(得分:1)
我不完全确定你对这些对象做了什么,但无论用户选择什么,你都指向一个时刻。 “5天前”是“星期四”,反之亦然。
因此,除非日期与网站一起滚动(例如“5天前的记录”仍然意味着星期四,明天等),当然这只是一个界面问题?如果是这种情况,我会在模型中使用单个值作为日期,并让表单和视图完成所有工作。
这解决了自动生成的管理方面的问题,因为你只需要一个字段来对抗,但除非你编写自己的表单窗口小部件并覆盖ModelAdmin类,否则它本身不会让你在两者之间做出选择。你的模特。
如果情况并非如此,请忽略此答案。