Django UpdateView not loading forms with styles

Viewed 209

I created a form using Django's UpdateView class, however, when the form loads it seems like the text boxes and text areas are not styled (looks like form.as_p style). Here is an example of exactly what I did.

Views.py

class UpdatePostView(UpdateView):
    template_name = 'Post/UpdatePost.html'
    model = Post
    fields = ['Title', 'Body']
    success_url = reverse_lazy('BlogApp:main')
  
    def form_valid(self, form):
        form.instance.Title = form.cleaned_data['Title']
        form.instance.Body = form.cleaned_data['Body']
        form.instance.save()
        
        return super().form_valid(form)

Here is how I loaded the form in UpdatePost.html:

<form id="UpdatePostForm" method="POST">
    {% csrf_token %}
    <div class="form-group">
        <label for="PostTitle">{{form.Title.label}}</label>
        {{form.Title}}         
    </div>
    
    <div class="form-group">
        <label for="PostBody">{{form.Body.label}}</label>
        {{form.Body}}
    </div>

    <input class="btn btn-primary" type="submit" for="UpdatePostForm" value="Update"> 
    </div>
</form>
2 Answers

If you use Bootstrap, you also can use django-crispy-forms (version for Bootstrap 4 https://github.com/django-crispy-forms/django-crispy-forms ,version for Bootstrap 5 - https://github.com/django-crispy-forms/crispy-bootstrap5). It is helpful to live DRY (Don't repeat yourself). And then it will be something like(I use crispy-forms for Bootstrap 5):

pip install crispy-bootstrap5

INSTALLED_APPS = (
    ...
    "crispy_forms",
    "crispy_bootstrap5",
    ...
)

CRISPY_ALLOWED_TEMPLATE_PACKS = "bootstrap5"

CRISPY_TEMPLATE_PACK = "bootstrap5"
class UpdatePostView(UpdateView):
    template_name = 'Post/UpdatePost.html'
    model = Post
    fields = ['Title', 'Body']
    success_url = reverse_lazy('BlogApp:main')
  
    def form_valid(self, form):
        form.instance.Title = form.cleaned_data['Title']
        form.instance.Body = form.cleaned_data['Body']
        form.instance.save()
        
        return super().form_valid(form)

template

{% extends 'base.html' %}
{% load crispy_forms_tags %}

{% block content %}

<h1 class="text-center">Update Post</h1>
<br />
        <form method="POST" enctype="multipart/form-data">
          {% csrf_token %} 
          {{form|crispy }}
            <button class="btn btn-outline-primary">
              Update 
            </button>
         </form>
{% endblock content %}

Because by default the form.body and form.title render a html input, you can override the class attribut from your UpdateView like that :

def get_form(self, *args, **kwargs):
        form = super(UpdatePostView, self).get_form(*args, **kwargs)
        form.fields["Title"].widget.attrs["class"] = "form-group"
        form.fields["Body"].widget.attrs["class"] = "form-group"
        return form
Related