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:
- Obligarlo a usar nuestro widget de entrada de radio personalizado
- 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>