这可能是简单的事情之一,我只是错过它,或者它可能只是非常困难。还不确定,但我知道我还没有找到死去的简单方法。
我有一个ModelMultipleChoiceField的扩展,我想在单个选项行上放置一些CSS类 - 我希望每一行从它选择的对象中获取它的类。具体来说,我正在选择志愿者机会,我希望白天对它们进行颜色编码。一个给定的事件(例如,一个志愿者机会)知道它何时开始,所以我可以从事件中获取日期,显然我可以在它上面打一个@property让它吐出像“星期五”这样的字符串但是我无法看到如何要求字段组织自己,以便每个选项通过引用该属性来添加一个类。
我也试过用这种造型来编写模板来制作自己,但这已经变得非常痛苦,而且效果不好,并且在维护方面可能会成为一个痛点,所以我'如果可以的话,我想进一步做这件事。
答案 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()
方法来执行自定义操作,但这可能是您为使其启动并运行所能做的最少的更改。