Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

287
Vistas
Django add attributes to SelectMultiple <option> tags

There's a great explanation here on adding attributes to <option> tags within a django form field. But this is only for a Select widget. I want to do the same for a SelectMultiple widget.

I tried the following (subclass Select and SelectMultiple and reference MySelectMultiple when creating the Model form field employees):

class MySelect(forms.Select):

    def __init__(self, *args, **kwargs):
            super(MySelect, self).__init__(*args, **kwargs)

    def render_option(self, selected_choices, option_value, option_label):
        # original forms.Select code #
        return u'<option custom_attribute="foo">...</option>'

class MySelectMultiple(MySelect):
    def __init__(self, *args, **kwargs):
        super(MySelectMultiple, self).__init__(*args, **kwargs) 

employees = forms.ModelMultipleChoiceField(
                    widget=MySelectMultiple(attrs={}),
                    queryset=Employee.objects.all(),
                )

But the rendered form is still showing as a Select widget, not a SelectMultiple widget.

I can provide attrs={'multiple':'multiple'} to MySelectMultiple to make the form field render as a multiple select widget - but when the form is saved, only a single value is saved (not multiple values)!

How can I have the form render as a multiple choice field AND save all of the selected values? Thank you.

about 4 years ago · Santiago Trujillo
3 Respuestas
Responde la pregunta

0

Your select multiple should inherit from SelectMultiple rather than Select:

class MySelectMultiple(SelectMultiple):
    def render_option(self, selected_choices, option_value, option_label):
        # original forms.Select code #
        return u'<option custom_attribute="foo">...</option>'

It looks like your __init__ method isn't necessary, since it just calls super().

about 4 years ago · Santiago Trujillo Denunciar

0

SelectMultiple inherits from Select, you just need to override the create_option method to get the same results:

class MySelectMultiple(forms.SelectMultiple):
    def create_option(self, name, value, *args, **kwargs):
        option = super().create_option(name, value, *args, **kwargs)
        if value:
            instance = self.choices.queryset.get(pk=value)  # get instance
            option['attrs']['custom_attr'] = instance.field_name  # set option attribute
        return option

about 4 years ago · Santiago Trujillo Denunciar

0

Alright, figured out: by using:

class MySelectMultiple(MySelect):
    def __init__(self, *args, **kwargs):
        super(MySelectMultiple, self).__init__(*args, **kwargs) 

I was still using the django native Select but just calling it MySelectMultiple. I needed to import the rest of SelectMultiple.

So, instead of:

class MySelectMultiple(MySelect):
    def __init__(self, *args, **kwargs):
        super(MySelectMultiple, self).__init__(*args, **kwargs) 

The class needs to be complete (copy/paste of native django code for SelectMultiple):

class MySelectMultiple(MySelect):
    allow_multiple_selected = True

    def __init__(self, *args, **kwargs):
        super(MySelectMultiple, self).__init__(*args, **kwargs)


    def render(self, name, value, attrs=None, choices=()):
        if value is None:
            value = []
        final_attrs = self.build_attrs(attrs, name=name)
        output = [format_html('<select multiple="multiple"{0}>', forms.utils.flatatt(final_attrs))]
        options = self.render_options(choices, value)
        if options:
            output.append(options)
        output.append('</select>')
        return mark_safe('\n'.join(output))

    def value_from_datadict(self, data, files, name):
        if isinstance(data, (MultiValueDict, MergeDict)):
            return data.getlist(name)
        return data.get(name, None)
about 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda