web-dev-qa-db-fra.com

Définir la classe css dans les formulaires Django

Suppose que j'ai un formulaire

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

Existe-t-il un moyen pour moi de définir des classes CSS sur chaque champ de sorte que je puisse ensuite utiliser jQuery en fonction de la classe dans ma page rendue?

J'espérais ne pas avoir à construire manuellement le formulaire.

169
ashchristopher

Répondu à ma propre question. Soupir

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

Je n'avais pas réalisé que cela avait été transmis au constructeur du widget.

82
ashchristopher

Encore une autre solution qui ne nécessite aucune modification du code python et qui est donc préférable pour les concepteurs et les modifications de présentation uniques: Django-widget-tweaks . J'espère que quelqu'un le trouvera utile.

173
Mikhail Korobov

Voici une autre solution pour ajouter des définitions de classe aux widgets après avoir déclaré les champs de la classe.

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

Utilisez Django-widget-tweaks , il est facile à utiliser et fonctionne plutôt bien.

Sinon, vous pouvez utiliser un filtre de modèle personnalisé.

En considérant que vous rendez votre formulaire de cette façon:

<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 est une instance de BoundField qui a la méthode as_widget.

vous pouvez créer un filtre personnalisé "addcss" dans "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})

Et ensuite appliquez votre filtre:

{% 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 sera ensuite rendu avec la classe css "MyClass".

J'espère que cette aide.

EDIT 1

  • Mise à jour du filtre en fonction de la réponse de dimyG

  • Ajouter un lien Django-widget-Tweak

EDIT 2

  • Mettre à jour le filtre en fonction du commentaire de Bhyd
40
Charlesthk

En développant la méthode indiquée sur docs.djangoproject.com:

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

Je pensais qu'il était gênant de connaître le type de widget natif pour chaque champ et je trouvais amusant de remplacer le paramètre par défaut simplement pour mettre un nom de classe sur un champ de formulaire. Cela semble fonctionner pour moi:

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'

Cela me semble un peu plus propre.

31
Dave

Si vous souhaitez que tous les champs du formulaire héritent d'une certaine classe, vous devez simplement définir une classe parent héritant de forms.ModelForm, puis en hériter

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

Cela m'a aidé à ajouter la classe 'form-control' à tous les champs de tous les formulaires de mon application automatiquement, sans ajouter de réplication de code. 

26
Oleg Belousov

Voici un moyen simple de changer de vue. ajouter ci-dessous dans la vue juste avant de le passer dans le modèle.

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

Ajoutez simplement les classes à votre formulaire comme suit.

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'
        }
    ))
13
paulc

Voici une variante de ce qui précède qui donnera la même classe à tous les champs (par exemple, jquery Nice coins arrondis).

  # 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'
4
timlinux

Vous pouvez essayer ça ..

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

Vous pouvez voir plus d'informations dans: Django Widgets

2
Andres Quiroga

Si vous souhaitez ajouter une classe au champ d'un formulaire dans un modèle (pas dans view.py ou form.py), par exemple dans le cas où vous souhaitez modifier des applications tierces sans redéfinir leurs vues, Le filtre de modèle décrit dans Charlesthkanswer est très pratique. Mais dans cette réponse, le filtre de modèle remplace toutes les classes existantes du champ. 

J'ai essayé d'ajouter ceci en tant que montage mais il a été suggéré d'écrire comme une nouvelle réponse.

Donc, voici une balise template qui respecte les classes existantes du champ:

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})
2
dimyG

Comme vous le savez, vous pouvez le faire dans le constructeur de formulaire ( init function) ou après l’initiation de la classe de formulaire. Ceci est parfois nécessaire si vous n’écrivez pas votre propre formulaire et que ce formulaire vient d’ailleurs -

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})
1
Niki.py

Vous pouvez également utiliser Django Crispy Forms , c’est un excellent outil pour définir des formulaires au cas où vous souhaiteriez utiliser un framework CSS comme Bootstrap ou Foundation. Et il est facile de spécifier des classes pour vos champs de formulaire.

Votre classe de formulaire aimerait ceci alors:

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'),
        )
    )
0
Dmitrii Mikhailov