[Django]-How to add custom styling to Forms created with Django CreateView

13๐Ÿ‘

โœ…

You could write a model form for Question and pass it to the create view,

class QuestionForm(forms.ModelForm):

    class Meta:
        model = Question
        fields = ('myfield1', 'myfield2) 
        widgets = {
        'myfield1': forms.TextInput(attrs={'class': 'myfieldclass'}),
        }

or you could override init method for specifying a certain class for every field,

def __init__(self, *args, **kwargs):
    super(QuestionForm, self).__init__(*args, **kwargs)
    self.fields['myfield1'].widget.attrs.update({'class' : 'myfieldclass'})

Then, pass it to the attribute form_class of CreateView,

class QuestionCreate(CreateView):
    model = Question
    form_class = QuestionForm
๐Ÿ‘คzaidfazil

7๐Ÿ‘

I had a similar problem in my Django application based on the Bootstrap framework. My first attempt:

# views.py
from django.views.generic.edit import UpdateView
from . import models

class ModuleUpdateView(UpdateView):
    model = models.Module
    fields = ['name', 'description', 'status']

looked as follow:

First attempt

Not very nice indeed! The second attempt implied defining a custom ModelForm for my view and applying all the customisations therein:

# forms.py
from .models import Module

class ModuleForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(ModuleForm, self).__init__(*args, **kwargs)
        for visible in self.visible_fields():
            visible.field.widget.attrs['class'] = 'form-control'

    class Meta:
        model = Module
        fields = ['name', 'description', 'status']

Please note the for cycle in __init__, which adds the form-control CSS class to all visible form fields. The CSS styling for form-control is provided by Bootstrap so I didnโ€™t even have to modify my stylesheets.

Once I have my custom ModelForm I can rewrite my View class as follows:

# views.py
from django.views.generic.edit import UpdateView
from . import forms, models

class ModuleUpdateView(UpdateView):
    model = models.Module
    form_class = forms.ModuleForm

and you can see the results below.

Second attempt

Far better!

Hope that helps, feel free to comment in case of questions.

๐Ÿ‘คSal Borrelli

4๐Ÿ‘

class FooForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(FooForm, self).__init__(*args, **kwargs)
        self.fields['field1'].widget.attrs = { 'class': 'fooclass' }

    class Meta:
        model = FooModel
        fields = ['field1', 'field2']

you cannot directly add css to the CreateView for that you need to create a ModelForm and use the form_class = FooForm in your create view, and in this ModelForm you can use specific class for the fields and use css to style them as needed

๐Ÿ‘คExprator

1๐Ÿ‘

The best way is to override the get_form function.

class QuestionCreate(CreateView):
    model = Question
    fields = ['title', 'body', 'category', 'MyField']

    def get_form(self, form_class=None):
        form = super(QuestionCreate, self).get_form(form_class)
        form['MyField'].field.widget.attrs.update({'class' : 'MyClass'})
        return form

Or if you want to add the attribute to all fields you can use a for-loop as follows:

class QuestionCreate(CreateView):
    model = Question
    fields = ['title', 'body', 'category', 'MyField']

    def get_form(self, form_class=None):
        form = super(OPCCreateView, self).get_form(form_class)
        for visible in form.visible_fields():
            visible.field.widget.attrs.update({'class' : 'MyClass'})
        return form
๐Ÿ‘คDeepBlue

0๐Ÿ‘

We can use django-crispy-forms if we want some bootstrap styling to the rendered form:

pip install django-crispy-forms

Then add โ€˜crispy-formsโ€™ to the installed apps.
Load the crispy_form_tags in the form template page and instead of {{form}} use {{form|crispy}}.

Documentation of Crispy.

๐Ÿ‘คallenjiji

Leave a comment