Agregar clase a la salida de Django label_tag ()

Necesito alguna forma de agregar un atributo de clase a la salida del método label_tag () para un campo de formularios.

Veo que existe la posibilidad de pasar en un diccionario de atributos y lo he probado en el shell y puedo hacer algo como:

for field in form: print field.label_tag(attrs{'class':'Foo'}) 

Veré la clase = ‘Foo’ en mi salida, pero no veo una manera de agregar un argumento de atributo desde la plantilla. De hecho, las plantillas están diseñadas específicamente para eso, ¿no?

¿Hay alguna forma en mi definición de formulario para definir la clase que se mostrará en la etiqueta?

En el formulario, puedo hacer lo siguiente para dar una clase a las entradas

 self.fields['some_field'].widget.attrs['class'] = 'Foo' 

Solo necesito que haga salir la clase para el también.

Una etiqueta de plantilla personalizada parece ser la solución. Un filtro personalizado también lo haría, aunque puede ser menos elegante. Pero tendría que recurrir a la representación personalizada de formularios en ambos casos.

Si esta es una tarea de gran importancia; Yo crearía un Mixin que me permita anotar los campos de formulario con clases de tags y proporciona métodos de representación de formularios usando esas clases. Para que funcione el siguiente código:

 {{ form.as_table_with_label_classes }} 

Pero me gustaría preguntar; ¿Realmente necesitas una clase en la etiqueta de la etiqueta? Me refiero a HTML en cuanto a diseño. ¿Es absolutamente necesario agregar una clase allí? No se pudo resolver con algún CSS como:

 encapsulating_selector label { some-attr: some-value; } 

A veces uso jQuery para tales casos donde; mejorará la página si funciona, pero no será un desastre si no lo hace . Y mantén la fuente HTML lo más magra posible.

Técnica 1

Estoy en desacuerdo con la afirmación de otra respuesta de que un filtro sería “menos elegante”. Como puedes ver, es muy elegante.

 @register.filter(is_safe=True) def label_with_classes(value, arg): return value.label_tag(attrs={'class': arg}) 

Usar esto en una plantilla es igual de elegante:

 {{ form.my_field|label_with_classes:"class1 class2"}} 

Técnica 2

Alternativamente, una de las técnicas más interesantes que he encontrado es: Agregar * a los campos obligatorios .

Usted crea un decorador para BoundField.label_tag que lo llamará con los atributos establecidos adecuadamente. Luego moneas el parche BoundField para que llamar a BoundField.label_tag llame a la función decorada

 from django.forms.forms import BoundField def add_control_label(f): def control_label_tag(self, contents=None, attrs=None): if attrs is None: attrs = {} attrs['class'] = 'control-label' return f(self, contents, attrs) return control_label_tag BoundField.label_tag = add_control_label(BoundField.label_tag) 

¿Qué hay de agregar la clase CSS al campo de formulario en forms.py, como:

 class MyForm(forms.Form): title = forms.CharField(widget=forms.TextInput(attrs={'class': 'foo'})) 

Luego solo hago lo siguiente en la plantilla:

  

Por supuesto, esto puede modificarse fácilmente para que funcione dentro de una etiqueta de bucle for en la plantilla.

Un poco demasiado tarde pero encontré un problema similar. Espero que esto te ayude.

 class MyForm(forms.ModelForm): def __init__(self, *args, **kwargs): super(MyForm, self).__init__(*args, **kwargs) self.fields['myfield1'].widget.attrs.update( {'class': 'form-control'}) self.fields['myfield2'].widget.attrs.update( {'class': 'form-control'}) def as_two_col_layout(self): return self._html_output( normal_row='
%(label)s
%(field)s%(help_text)s
', error_row='%s', row_ender='', help_text_html=' %s', errors_on_separate_row=True) class Meta: model = mymodel fields = ['myfield1', 'myfield2']

Estoy de acuerdo con la respuesta número uno, con css esto podría hacerse, pero. ¿Cuál es la resonancia para que esto esté en la fuente de django?

En django.forms.forms.py hay esta definición que muestra que hay código para mostrar los atributos en las tags:

 class BoundField(StrAndUnicode): # .... def label_tag(self, contents=None, attrs=None): contents = u'' % (widget.id_for_label(id_), attrs, unicode(contents)) 

pero _html_output llama a esta función sin atributos:

 label = bf.label_tag(label) or '' 

Así que parece que django está parcialmente preparado para esto, pero en realidad no lo usa.

 @register.simple_tag def advanced_label_tag(field): """ Return form field label html marked to fill by `*` """ classes = [] attrs = {} contents = force_unicode(escape(field.label)) if field.field.required: classes.append(u'required') contents = force_unicode('%s *'%escape(field.label)) if classes: attrs['class'] = u' '.join(classes) return field.label_tag(contents=contents, attrs=attrs) 
 class CustomBoundField(BoundField): def label_tag(self, contents=None, attrs=None): if self.field.required: attrs = {'class': 'required'} return super(CustomBoundField, self).label_tag(contents, attrs) class ImportViewerForm(forms.Form): url = fields.URLField(widget=forms.TextInput(attrs={'class': 'vTextField'})) type = fields.ChoiceField(choices=[('o', 'Organisation'), ('p', 'Program')], widget=forms.RadioSelect, help_text='Url contain infornation about this type') source = fields.ChoiceField(choices=[('h', 'hodex'), ('s', 'studyfinder')], initial='h', widget=forms.RadioSelect) def __getitem__(self, name): "Returns a BoundField with the given name." try: field = self.fields[name] except KeyError: raise KeyError('Key %r not found in Form' % name) return CustomBoundField(self, field, name) class Media: css = {'all': [settings.STATIC_URL + 'admin/css/forms.css']} 

Necesita cambiar el método label_tag en la clase BoundField y usarlo en la forma