1 votes

<option>Contrôle de niveau des entrées Select à l'aide de l'API Django Forms.

Je souhaite ajouter un attribut label= à un élément d'option d'une entrée de formulaire Select à l'aide de l'API Django Forms sans écraser la méthode render_options du widget Select. Est-ce possible, et si oui, comment ?

Remarque : je souhaite ajouter un libellé directement à l'option (ceci est valide dans la norme XHTML Strict) pas un optgroup.

2voto

Luper Rouch Points 5033

Je viens d'écrire une classe pour faire ça :

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)

Ejemplo:

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

1voto

Jarret Hardie Points 36266

J'ai bien peur que cela ne soit pas possible sans sous-classer l'élément Select pour fournir votre propre rendu, comme vous l'avez deviné. Le site code pour Select ne comprend pas d'attributs pour chaque <option> point. Il couvre la valeur de l'option, le statut "sélectionné" et l'étiquette... c'est tout, je le crains :

def render_option(option_value, option_label):
    option_value = force_unicode(option_value)
    selected_html = (option_value in selected_choices) and u' selected="selected"' or ''
    return u'<option value="%s"%s>%s</option>' % (
        escape(option_value), selected_html,
        conditional_escape(force_unicode(option_label)))

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X