Saltar al contenido

Personalizar formularios de Django con el widget RadioSelect

Solución:

En mi código descubrí que cambiar el widget de

forms.RadioSelect

para

forms.RadioSelect(attrs={'id': 'value'})

mágicamente causa el resultado tag valor para incluir el id atributo con el índice del artículo adjunto. Si utiliza

{% for radio in form.foo %}
    <li>
        {{ radio }}
    </li>
{% endfor %}

en la forma que obtienes un label envuelto alrededor de un input. Si quieres lo mas convencional input seguido por label, Usted necesita hacer ésto:

{% for radio in form.value %}
    <li>
        {{ radio.tag }}
        <label for="value_{{ forloop.counter0 }}">{{ radio.choice_label }}</label>
    </li>
{% endfor %}

Desafortunadamente, esto es más complicado de lo que debería ser, parece que necesita anular al menos 2 clases: RadioRenderer y RadioInput. Lo siguiente debería ayudarlo a comenzar, pero es posible que deba modificarlo un poco.

Primero cree un widget de entrada de botón de opción personalizado. El único propósito de que anulemos el método de renderizado es deshacernos de la molesta estructura que Django impone (<label><input /></label>) donde en cambio queremos el nuestro (<label /><input />):

class CustomRadioInput(RadioInput):
    def render(self, name=None, value=None, attrs=None, choices=()):
        name = name or self.name
        value = value or self.value
        attrs = attrs or self.attrs
        if 'id' in self.attrs:
            label_for=" for="%s_%s"" % (self.attrs['id'], self.index)
        else:
            label_for=""
            choice_label = conditional_escape(force_unicode(self.choice_label))
            return mark_safe(u'%s<label%s>%s</label>' % (self.tag(), label_for, choice_label))

Ahora tenemos que anular RadioRenderer con el fin de:

  1. Obligarlo a usar nuestro widget de entrada de radio personalizado
  2. Eliminar <li> envolver cada campo de entrada y <ul> envolviendo todos los campos de entrada:

Algo en estas líneas debería funcionar:

class RadioCustomRenderer(RadioFieldRenderer):
    def __iter__(self):
        for i, choice in enumerate(self.choices):
            yield CustomRadioInput(self.name, self.value, self.attrs.copy(), choice, i)

    def __getitem__(self, idx):
        choice = self.choices[idx]
        return CustomRadioInput(self.name, self.value, self.attrs.copy(), choice, idx)

    def render(self):
        return mark_safe(u'%s' % u'n'.join([u'%s' % force_unicode(w) for w in self]))

Finalmente, indique a Django que use un renderizador personalizado

notify_new_friends = forms.ChoiceField(label="Notify when new friends join", widget=forms.RadioSelect(renderer=RadioCustomRenderer), choices=NOTIFICATION_CHOICES)

Por favor tenga en cuenta: Esto ahora genera botones de radio junto con <td> por lo tanto, debe crear una tabla a su alrededor en su plantilla, algo así:

<table>
  <tr>
    <td><label for="{{field.auto_id}}">{{field.label}}</label></td>
    <td>{{ field.errors }} {{field}}</td>
  </tr>
</table>
¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *