Django Forms API 中 Select 输入的等级控制

在使用 Django Forms API 时,用户希望为 Select 表单输入的选项元素添加一个 label 属性,而无需覆盖 Select 小部件的 render_options 方法。那么,这是否可行?如果可行,该如何操作?

注意:用户希望直接将标签添加到选项中(这在 XHTML Strict 标准中是有效的),而不是将标签添加到 optgroup 中。

2、解决方案

方法一:创建自定义 Select 子类

from django.forms.widgets import Select
from django.utils.encoding import force_unicode
from itertools import chain
from django.utils.html import escape, conditional_escape


class ExtendedSelect(Select):
    """
    A subclass of Select that adds the possibility to define additional 
    properties on options.

    It works as Select, except that the ``choices`` parameter takes a list of
    3 elements tuples containing ``(value, label, attrs)``, where ``attrs``
    is a dict containing the additional attributes of the option.
    """

    def render_options(self, choices, selected_choices):
        def render_option(option_value, option_label, attrs):
            option_value = force_unicode(option_value)
            selected_html = (option_value in selected_choices) and u' selected="selected"' or ''
            attrs_html = []
            for k, v in attrs.items():
                attrs_html.append('%s="%s"' % (k, escape(v)))
            if attrs_html:
                attrs_html = " " + " ".join(attrs_html)
            else:
                attrs_html = ""
            return u'<option value="%s"%s%s>%s</option>' % (
                escape(option_value), selected_html, attrs_html,
                conditional_escape(force_unicode(option_label)))
        # Normalize to strings.
        selected_choices = set([force_unicode(v) for v in selected_choices])
        output = []
        for option_value, option_label, option_attrs in chain(self.choices, choices):
            if isinstance(option_label, (list, tuple)):
                output.append(u'<optgroup label="%s">' % escape(force_unicode(option_value)))
                for option in option_label:
                    output.append(render_option(*option))
                output.append(u'</optgroup>')
            else:
                output.append(render_option(option_value, option_label,
                    option_attrs))
        return u'\n'.join(output)

Example:
select = ExtendedSelect(choices=(
        (1, "option 1", {"label": "label 1"}),
        (2, "option 2", {"label": "label 2"}),
    ))

方法二:直接覆盖 Select 小部件的 render_option 方法

# Django 1.8 and earlier
class MySelect(Select):
    def render_option(self, selected_choices, option_value, option_label):
        if option_value in selected_choices:
            selected_html = ' selected="selected"'
        else:
            selected_html = ''
        return '<option value="%s"%s>%s</option>' % (
            escape(option_value), selected_html,
            conditional_escape(force_unicode(option_label))
        )

# Django 1.9+
class MySelect(Select):
    def render_option(self, selected_choices, option_value, option_label, attrs=None):
        if option_value in selected_choices:
            selected_html = ' selected="selected"'
        else:
            selected_html = ''
        html = '<option value="%s"%s>%s</option>' % (
            escape(option_value), selected_html,
            conditional_escape(force_unicode(option_label))
        )
        if attrs:
            for k, v in sorted(attrs.items()):
                html = html + ' %s="%s"' % (escape(k), escape(v))
        return html

无论选择哪种方法,都可以实现为 Select 表单输入的选项元素添加 label 属性的目的。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值