Django - 动态地添加Css类以形成字段选项

时间:2015-08-07 10:40:09

标签: django django-forms

这可能是简单的事情之一,我只是错过它,或者它可能只是非常困难。还不确定,但我知道我还没有找到死去的简单方法。

我有一个ModelMultipleChoiceField的扩展,我想在单个选项行上放置一些CSS类 - 我希望每一行从它选择的对象中获取它的类。具体来说,我正在选择志愿者机会,我希望白天对它们进行颜色编码。一个给定的事件(例如,一个志愿者机会)知道它何时开始,所以我可以从事件中获取日期,显然我可以在它上面打一个@property让它吐出像“星期五”这样的字符串但是我无法看到如何要求字段组织自己,以便每个选项通过引用该属性来添加一个类。

我也试过用这种造型来编写模板来制作自己,但这已经变得非常痛苦,而且效果不好,并且在维护方面可能会成为一个痛点,所以我'如果可以的话,我想进一步做这件事。

1 个答案:

答案 0 :(得分:0)

不得不定制很多django形式,我感到痛苦。我想我明白你要做的是什么,我相信有一个解决方案。

django.forms.models中,为ModelMultipleChoiceField定义的窗口小部件为SelectMultiple,位于django.forms.widgets。这负责整个窗口小部件的呈现,但是如果你查看窗口小部件的render方法,它实际上是将render_options的结果包装在<select> HTML元素中。

render_options方法位于父Select窗口小部件上,后者又在同一个类上调用render_option方法。这是呈现每个<option>元素的实际HTML的位置,以及您可以在哪里挂钩以添加HTML属性。您在此处获得了option_value属性,因此您可以检查所需的内容,并确定您希望在HTML中包含哪些属性。您将负责返回HTML,因此您可以复制/拼写功能并根据需要进行修改(这就是为什么这很痛苦)。请参阅github上的here以供参考。

您必须为此定义SelectMultiple的窗口小部件子类,并将其作为窗口小部件分配给您的字段;要做到这一点,做下面的事情(取决于你是否需要任何运行时参数为您的小部件实例):

class MyWidgetSubclass(SelectMultiple):

    def render_option(selected_choices, option_value, option_label):

        my_fancy_new_html_for_the_option = ...
        ... your code here ...
        return my_fancy_new_html_for_the_option

class MyForm(Form):

    my_field = ModelMultipleChoiceField(widget=MyWidgetSubclass)

    # or

    def __init__(*args, **kwargs):  # Not the real params, of course

       super(MyForm, self).__init__(*args, **kwargs)

       # You'll probably need to pass arguments to the instantiation.
       self.fields['my_field'].widget = MyWidgetSubclass()

所以是的,这非常hacky,并想知道是否有更简单的方法来做到这一点。如果有,我很高兴知道,因为我们必须在我们工作场所的几个地方做这件事,每次都感觉很脏(混合标记与功能不是我最喜欢的)。您可以完全覆盖窗口小部件的render()方法来执行自定义操作,但这可能是您为使其启动并运行所能做的最少的更改。