2009-01-05 11 views
23

Necesito alguna manera de añadir un atributo de la clase a la salida del método label_tag() para un campo de formas.Añadir a la clase Django label_tag() de salida

veo que existe la posibilidad de pasar de un diccionario attrs y he probado entonces en el soporte y puedo hacer algo como:

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

voy a ver la clase = 'Foo' en mi salida, pero no veo una manera de agregar un argumento attrs desde la plantilla, de hecho, las plantillas están diseñadas específicamente contra eso, ¿no?

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

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

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

que sólo hay que tenerlo salida de la clase para el también.

Respuesta

8

Un custom template tag 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 de formularios personalizados en ambos casos.

Si esta es una tarea de gran importancia; Crearía un Mixin que me permite anotar los campos de formulario con clases de etiqueta y los suministros de los métodos de representación utilizando esas clases. Para que el siguiente código funcione:

{{ form.as_table_with_label_classes }} 

Pero me gustaría preguntar; ¿Realmente necesitas una clase en la etiqueta? Me refiero a HTML en cuanto al diseño. Es absolutamente necesario agregar una clase allí? No podía ser resuelto con un poco de CSS, como:

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

veces uso jQuery para los casos en que; mejorará la página si funciona, pero no será un desastre si no lo hace. Y mantenga la fuente HTML lo más ajustada posible.

+34

'¿Realmente necesita una clase en la etiqueta de etiqueta?', Sí, si está utilizando un marco como bootstrap o base. – vikki

1

estoy de acuerdo con la respuesta número uno, con css esto se podría hacer, pero. ¿Cuál es la resonancia de esto en la fuente django?

En django.forms.forms.py hay esta definición que muestra que hay código para mostrar en attrs etiquetas:

class BoundField(StrAndUnicode): 
# .... 
def label_tag(self, contents=None, attrs=None): 
    contents = u'<label for="%s"%s>%s</label>' % (widget.id_for_label(id_), attrs, unicode(contents)) 

pero _html_output llamadas a esta función sin attrs:

label = bf.label_tag(label) or '' 

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

11

¿Qué hay de adquirir esta clase de CSS para el campo de formulario en el forms.py, como:

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

entonces simplemente hacer lo siguiente en la plantilla:

<label for="id_{{form.title.name}}" class="bar"> 
    {{ form.title }} 
</label> 

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

+9

Puede usar {{form.title.auto_id}} en lugar de asumir el prefijo "id_". – matthewwithanm

0
@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 <span>*</span>'%escape(field.label)) 

    if classes: 
     attrs['class'] = u' '.join(classes) 

    return field.label_tag(contents=contents, attrs=attrs) 
16

Técnica 1

estoy de acuerdo con la afirmación de otra respuesta 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}) 

El uso de este en una plantilla es tan elegante:

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

Técnica 2

Alternativamente, una de las técnicas más interesante que he encontrado es: Adding * to required fields.

Crea un decorador para BoundField.label_tag que lo llamará con attrs configurado correctamente. A continuación, conectó 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)  
+4

La técnica 1 me está dando el objeto "AttributeError: 'SafeText' no tiene el atributo 'label_tag'" con Django 1.6. ¿Podrías por favor verificar? –

+0

Es por un espacio. Elimine el espacio cuando escriba el filtro, antes y después | – tilaprimera

+0

@AdamSilver ¿Encontró una solución para esto? – Anuj

0
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']} 

usted necesita método label_tag cambio en la clase BoundField, y lo utilizan en forma

+0

Esto funciona bien para las formas normales. Pero recibo errores cuando aplico el mismo arreglo a ModelForms. –

1

Un poco demasiado tarde, pero se encontró con 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='<div class="form-group"><span class="col-xs-2">%(label)s</span> <div class="col-xs-10">%(field)s%(help_text)s</div></div>', 
      error_row='%s', 
      row_ender='</div>', 
      help_text_html=' <span class="helptext">%s</span>', 
      errors_on_separate_row=True) 

    class Meta: 

     model = mymodel 
     fields = ['myfield1', 'myfield2'] 
+0

Intento utilizar este método, pero la etiqueta no tiene un estilo. ¿Me puedes mostrar tu plantilla? Tengo esto en mi plantilla: {% for field in form%} {{field.label_tag}} {{field}} {% if field.help_text%} {{field.help_text | safe}} {% endif%} {% endfor%} Parece que el html_output no se aplica ... – cwhisperer

+0

o solo se usa cuando se usa as_table(), as_ul(), as_p()? – cwhisperer

+1

@cwhisperer en su plantilla que debe usar como form.as_two_col_layout y el código hará el trabajo. –

Cuestiones relacionadas