In Django form, custom SelectField and SelectMultipleField

后端 未结 5 1634
野趣味
野趣味 2021-01-02 16:11

I am using Django everyday now for three month and it is really great. Fast web application development.

I have still one thing that I cannot do exactly how I want t

5条回答
  •  遥遥无期
    2021-01-02 16:46

    What you need to do, is to change the output which is controlled by the widget. Default is the select widget, so you can subclass it. It looks like this:

    class Select(Widget):
        def __init__(self, attrs=None, choices=()):
            super(Select, self).__init__(attrs)
            # choices can be any iterable, but we may need to render this widget
            # multiple times. Thus, collapse it into a list so it can be consumed
            # more than once.
            self.choices = list(choices)
    
        def render(self, name, value, attrs=None, choices=()):
            if value is None: value = ''
            final_attrs = self.build_attrs(attrs, name=name)
            output = [u'' % flatatt(final_attrs)]
            options = self.render_options(choices, [value])
            if options:
                output.append(options)
            output.append('')
            return mark_safe(u'\n'.join(output))
    
        def render_options(self, choices, selected_choices):
            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'' % (
                    escape(option_value), selected_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 in chain(self.choices, choices):
                if isinstance(option_label, (list, tuple)):
                    output.append(u'' % escape(force_unicode(option_value)))
                    for option in option_label:
                        output.append(render_option(*option))
                    output.append(u'')
                else:
                    output.append(render_option(option_value, option_label))
            return u'\n'.join(output)
    

    It's a lot of code. But what you need to do, is to make your own widget with an altered render method. It's the render method that determines the html that is created. In this case, it's the render_options method you need to change. Here you could include some check to determine when to add a class, which you could style.

    Another thing, in your code above it doesn't look like you append the last group choices. Also you might want to add an order_by() to the queryset, as you need it to be ordered by the type. You could do that in the init method, so you don't have to do it all over when you use the form field.

提交回复
热议问题