Django - 添加 Css 类 到表单字段选项,动态
Django - Adding Css Classes To Form Field Options, Dynamically
这是其中一件可能非常简单的事情,我只是想念它,或者它可能非常困难。还不确定,但我知道我还没有找到最简单的方法来做到这一点。
我有 ModelMultipleChoiceField 的扩展,我想在各个选项行上添加一些 CSS classes - 我希望每一行都得到它的 class 来自它正在选择的对象。具体来说,我正在选择志愿者机会,我想按天对它们进行颜色编码。一个给定的事件(例如,一个志愿者机会)知道它什么时候开始,所以我可以从事件中获取日期,显然我可以在它上面打一个 @属性 让它吐出一个字符串,比如 "friday" 但我看不出如何要求该字段自行组织,以便每个选项都通过引用 属性 添加到它的 class。
我也试过编写模板来生成自己的这种样式,但这变得非常痛苦,而且效果不是很好,而且在维护方面可能会成为一个痛点,所以如果可以的话,我想更进一步。
不得不自定义很多 django 表单,我感受到了你的痛苦。我想我明白你想做什么,我相信有一个解决方案。
在 django.forms.models
中,为 ModelMultipleChoiceField
定义的小部件是 SelectMultiple
,它位于 django.forms.widgets
中。这负责整个小部件的呈现,但是如果您查看小部件的 render
方法,它实际上是将 render_options
的结果包装在 <select>
HTML 元素.
render_options
方法在父 Select
小部件上,后者又在同一个 class 上调用 render_option
方法。这是每个 <option>
元素的实际 HTML 被呈现的地方,您可以在其中添加 HTML 属性。此处为您提供了 option_value
属性,因此您可以检查所需的任何内容并确定要包含在 HTML 中的 attribute/s。您将负责返回 HTML,因此您可以 copy/pasta 函数并根据需要进行修改(这就是为什么这很痛苦)。请参阅 github 上的 here 以供参考。
您必须为此定义 SelectMultiple
的小部件子 class,并将其作为小部件分配给您的字段;为此,请执行如下操作(取决于您的小部件实例是否需要任何运行时参数):
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()
所以是的,这很老套,想知道是否有更简单的方法来做到这一点。如果有的话,我很乐意知道,因为我们不得不在我们工作场所的几个地方这样做,而且每次都感觉很脏(混合标记和功能不是我最喜欢的)。您可以完全重写小部件的 render()
方法来执行一些自定义操作,但这可能是您为启动它所做的最少更改 运行.
这是其中一件可能非常简单的事情,我只是想念它,或者它可能非常困难。还不确定,但我知道我还没有找到最简单的方法来做到这一点。
我有 ModelMultipleChoiceField 的扩展,我想在各个选项行上添加一些 CSS classes - 我希望每一行都得到它的 class 来自它正在选择的对象。具体来说,我正在选择志愿者机会,我想按天对它们进行颜色编码。一个给定的事件(例如,一个志愿者机会)知道它什么时候开始,所以我可以从事件中获取日期,显然我可以在它上面打一个 @属性 让它吐出一个字符串,比如 "friday" 但我看不出如何要求该字段自行组织,以便每个选项都通过引用 属性 添加到它的 class。
我也试过编写模板来生成自己的这种样式,但这变得非常痛苦,而且效果不是很好,而且在维护方面可能会成为一个痛点,所以如果可以的话,我想更进一步。
不得不自定义很多 django 表单,我感受到了你的痛苦。我想我明白你想做什么,我相信有一个解决方案。
在 django.forms.models
中,为 ModelMultipleChoiceField
定义的小部件是 SelectMultiple
,它位于 django.forms.widgets
中。这负责整个小部件的呈现,但是如果您查看小部件的 render
方法,它实际上是将 render_options
的结果包装在 <select>
HTML 元素.
render_options
方法在父 Select
小部件上,后者又在同一个 class 上调用 render_option
方法。这是每个 <option>
元素的实际 HTML 被呈现的地方,您可以在其中添加 HTML 属性。此处为您提供了 option_value
属性,因此您可以检查所需的任何内容并确定要包含在 HTML 中的 attribute/s。您将负责返回 HTML,因此您可以 copy/pasta 函数并根据需要进行修改(这就是为什么这很痛苦)。请参阅 github 上的 here 以供参考。
您必须为此定义 SelectMultiple
的小部件子 class,并将其作为小部件分配给您的字段;为此,请执行如下操作(取决于您的小部件实例是否需要任何运行时参数):
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()
所以是的,这很老套,想知道是否有更简单的方法来做到这一点。如果有的话,我很乐意知道,因为我们不得不在我们工作场所的几个地方这样做,而且每次都感觉很脏(混合标记和功能不是我最喜欢的)。您可以完全重写小部件的 render()
方法来执行一些自定义操作,但这可能是您为启动它所做的最少更改 运行.