Pregunta

Supongamos que tengo un formulario

class SampleClass(forms.Form):
    name = forms.CharField(max_length=30)
    age = forms.IntegerField()
    django_hacker = forms.BooleanField(required=False)

¿Hay alguna manera de definir clases de css en cada campo para que luego pueda usar jQuery en función de la clase en mi página representada?

Esperaba no tener que compilar manualmente el formulario.

¿Fue útil?

Solución 2

Respondí mi propia pregunta. Sigh

http: //docs.djangoproject .com / en / dev / ref / forms / widgets / # django.forms.Widget.attrs

No me di cuenta de que se había pasado al constructor de widgets.

Otros consejos

Otra solución que no requiere cambios en el código de Python y, por lo tanto, es mejor para los diseñadores y los cambios de presentación únicos: django-widget-tweaks . Espero que alguien lo encuentre útil.

Aquí hay otra solución para agregar definiciones de clase a los widgets después de declarar los campos en la clase.

def __init__(self, *args, **kwargs):
    super(SampleClass, self).__init__(*args, **kwargs)
    self.fields['name'].widget.attrs['class'] = 'my_class'

Utilice django-widget-tweaks , Es fácil de usar y funciona bastante bien.

De lo contrario, esto se puede hacer usando un filtro de plantilla personalizado.

Teniendo en cuenta que representa su formulario de esta manera:

<form action="/contact/" method="post">
    {{ form.non_field_errors }}
    <div class="fieldWrapper">
        {{ form.subject.errors }}
        <label for="id_subject">Email subject:</label>
        {{ form.subject }}
    </div>
</form>

form.subject es una instancia de BoundField que tiene el método as_widget .

puede crear un filtro personalizado " addcss " en " my_app / templatetags / myfilters.py "

from django import template

register = template.Library()

@register.filter(name='addcss')
def addcss(value, arg):
    css_classes = value.field.widget.attrs.get('class', '').split(' ')
    if css_classes and arg not in css_classes:
        css_classes = '%s %s' % (css_classes, arg)
    return value.as_widget(attrs={'class': css_classes})

Y luego aplica tu filtro:

{% load myfilters %}
<form action="/contact/" method="post">
    {{ form.non_field_errors }}
    <div class="fieldWrapper">
        {{ form.subject.errors }}
        <label for="id_subject">Email subject:</label>
        {{ form.subject|addcss:'MyClass' }}
    </div>
</form>

form.subjects se procesará con el " MyClass " clase css.

Espero esta ayuda.

EDIT 1

  • Actualice el filtro de acuerdo con la dimyG respuesta de

  • Añadir enlace django-widget-tweak

EDIT 2

  • Actualizar el filtro de acuerdo con el comentario de Bhyd

Ampliando el método al que apunta docs.djangoproject.com:

class MyForm(forms.Form): 
    comment = forms.CharField(
            widget=forms.TextInput(attrs={'size':'40'}))

Pensé que era molesto tener que saber el tipo de widget nativo para cada campo, y me pareció gracioso anular el valor predeterminado solo para poner un nombre de clase en un campo de formulario. Esto parece funcionar para mí:

class MyForm(forms.Form): 
    #This instantiates the field w/ the default widget
    comment = forms.CharField()

    #We only override the part we care about
    comment.widget.attrs['size'] = '40'

Esto me parece un poco más limpio.

Si desea que todos los campos del formulario hereden una determinada clase, simplemente defina una clase primaria, que hereda de forms.ModelForm , y luego herede de ella

class BaseForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(BaseForm, self).__init__(*args, **kwargs)
        for field_name, field in self.fields.items():
            field.widget.attrs['class'] = 'someClass'


class WhateverForm(BaseForm):
    class Meta:
        model = SomeModel

Esto me ayudó a agregar la clase 'form-control' a todos los campos en todos los formularios de mi aplicación automáticamente, sin agregar replicación de código.

Aquí hay una manera simple de alterar a la vista. agregue a continuación en la vista justo antes de pasarlo a la plantilla.

form = MyForm(instance = instance.obj)
form.fields['email'].widget.attrs = {'class':'here_class_name'}

Simplemente agregue las clases a su formulario de la siguiente manera.

class UserLoginForm(forms.Form):
    username = forms.CharField(widget=forms.TextInput(
        attrs={
        'class':'form-control',
        'placeholder':'Username'
        }
    ))
    password = forms.CharField(widget=forms.PasswordInput(
        attrs={
        'class':'form-control',
        'placeholder':'Password'
        }
    ))

Aquí hay una variación de lo anterior que dará a todos los campos la misma clase (por ejemplo, esquinas redondeadas de jquery nice).

  # Simple way to assign css class to every field
  def __init__(self, *args, **kwargs):
    super(TranslatedPageForm, self).__init__(*args, **kwargs)
    for myField in self.fields:
      self.fields[myField].widget.attrs['class'] = 'ui-state-default ui-corner-all'

En caso de que desee agregar una clase al campo de formulario en una plantilla (no en view.py o form.py), por ejemplo, en los casos en que desee modificar aplicaciones de terceros sin anular sus vistas, luego es muy conveniente un filtro de plantilla como se describe en Charlesthk respuesta . Pero en esta respuesta, el filtro de plantilla anula cualquier clase existente que pueda tener el campo.

Intenté agregar esto como una edición, pero se sugirió que se escribiera como una nueva respuesta.

Entonces, aquí hay una etiqueta de plantilla que respeta las clases existentes del campo:

from django import template

register = template.Library()


@register.filter(name='addclass')
def addclass(field, given_class):
    existing_classes = field.field.widget.attrs.get('class', None)
    if existing_classes:
        if existing_classes.find(given_class) == -1:
            # if the given class doesn't exist in the existing classes
            classes = existing_classes + ' ' + given_class
        else:
            classes = existing_classes
    else:
        classes = given_class
    return field.as_widget(attrs={"class": classes})

Puedes probar esto ...

class SampleClass(forms.Form):
  name = forms.CharField(max_length=30)
  name.widget.attrs.update({'class': 'your-class'})
...

Puede ver más información en: Widgets de Django

Resulta que puedes hacer esto en el constructor de formularios (función init ) o después de que se haya iniciado la clase de formulario. Esto a veces es necesario si no está escribiendo su propio formulario y ese formulario proviene de otro lugar -

def some_view(request):
    add_css_to_fields = ['list','of','fields']
    if request.method == 'POST':
        form = SomeForm(request.POST)
        if form.is_valid():
            return HttpResponseRedirect('/thanks/')
    else:
        form = SomeForm()

    for key in form.fields.keys():
        if key in add_css_to_fields:
            field = form.fields[key]
            css_addition = 'css_addition '
            css = field.widget.attrs.get('class', '')
            field.widget.attrs['class'] = css_addition + css_classes

    return render(request, 'template_name.html', {'form': form})

También puede usar Django Crispy Forms , es una excelente Herramienta para definir formularios en caso de que desee utilizar algún marco de CSS como Bootstrap o Foundation. Y es fácil especificar las clases para los campos de formulario allí.

A tu clase de formulario le gustaría esto entonces:

from django import forms

from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, Div, Submit, Field
from crispy_forms.bootstrap import FormActions

class SampleClass(forms.Form):
    name = forms.CharField(max_length=30)
    age = forms.IntegerField()
    django_hacker = forms.BooleanField(required=False)

    helper = FormHelper()
    helper.form_class = 'your-form-class'
    helper.layout = Layout(
        Field('name', css_class='name-class'),
        Field('age', css_class='age-class'),
        Field('django_hacker', css-class='hacker-class'),
        FormActions(
            Submit('save_changes', 'Save changes'),
        )
    )
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top