Skip to main content

Integrate Forms in view

Introduction

Django forms can be rendered as HTML forms using the as_p, as_table, or as_ul methods, which generate HTML code that can be included in a web page. You can also customize the appearance of forms by using CSS or by rendering the form fields manually.

For this purpose, view should send form to user. Each view follows the same pattern:

  • On a GET request, create an empty form and pass it to the template.
  • On a POST request, bind the form to request.POST, call is_valid(), and only then save or use the cleaned data.

The views we wrote in the Write Views topic already follow this pattern. Let's walk through each form.

SignUp Form

In signup() in views.py, a GET request renders an empty SignUpForm:

blog/views.py
signupForm = SignUpForm()
return render(request, 'signup.html', {'signupForm': signupForm})

and a POST request binds the submitted data, validates it and saves the new user:

blog/views.py
if request.method == 'POST':
signupForm = SignUpForm(request.POST)
if signupForm.is_valid():
signupForm.save()
return redirect('signin')

signupForm.save() creates the user with a properly hashed password — we never touch request.POST['password'] ourselves.

note

I will create html files in later topics.

Login Form

In signin() in views.py, a GET request renders an empty LoginForm:

blog/views.py
loginForm = LoginForm()
return render(request, 'signin.html', {'loginForm': loginForm})

On POST, the validated data is read from loginForm.cleaned_data and handed to authenticate(), which compares the password against the stored hash and returns the user or None.

Post Form

In create_post() in views.py, a GET request renders an empty BlogForm:

blog/views.py
blogForm = BlogForm()
return render(request, 'create_post.html', {'postForm': blogForm})

On POST, note two details:

blog/views.py
blogForm = BlogForm(request.POST, request.FILES)
if blogForm.is_valid():
blog = blogForm.save(commit=False)
blog.author = request.user
blog.save()
  • request.FILES must be passed as well, because the form contains an ImageField.
  • save(commit=False) returns an unsaved Blog instance so the view can attach author (which is not a form field) before saving.

Comment Form

The comment form is not rendered by the comment() view — it is shown on the post detail page. That's why get_post_by_id() passes an empty CommentForm to post_detail.html:

blog/views.py
commentForm = CommentForm()
return render(
request,
'post_detail.html',
{'post': post, 'comments': comments, 'commentForm': commentForm},
)

The template submits that form to post/<int:id>/comments/, and comment(request, id) handles the POST, attaches the blog and the author, saves, and redirects back to the post.

Final File

After adding above code, views.py should look like following:

blog/views.py
from django.contrib.auth import authenticate, login
from django.http import HttpResponse
from django.shortcuts import get_object_or_404, redirect, render

from .forms import BlogForm, CommentForm, LoginForm, SignUpForm
from .models import Blog, Comment


def home(request):
return HttpResponse("Hello, World. You're at the blog's home Page.")


def signup(request):
if request.method == 'POST':
signupForm = SignUpForm(request.POST)
if signupForm.is_valid():
signupForm.save()
return redirect('signin')
return render(request, 'signup.html', {'signupForm': signupForm})

signupForm = SignUpForm()
return render(request, 'signup.html', {'signupForm': signupForm})


def signin(request):
if request.method == 'POST':
loginForm = LoginForm(request.POST)
if loginForm.is_valid():
user = authenticate(
request,
username=loginForm.cleaned_data['username'],
password=loginForm.cleaned_data['password'],
)
if user is not None:
login(request, user)
return redirect('posts')
return HttpResponse("Invalid username or password.")

loginForm = LoginForm()
return render(request, 'signin.html', {'loginForm': loginForm})


def create_post(request):
if request.method == 'POST':
blogForm = BlogForm(request.POST, request.FILES)
if blogForm.is_valid():
blog = blogForm.save(commit=False)
blog.author = request.user
blog.save()
return redirect('post', id=blog.id)
return render(request, 'create_post.html', {'postForm': blogForm})

blogForm = BlogForm()
return render(request, 'create_post.html', {'postForm': blogForm})


def get_all_posts(request):
posts = Blog.objects.all()
return render(request, 'posts.html', {'posts': posts})


def get_post_by_id(request, id):
post = get_object_or_404(Blog, id=id)
comments = Comment.objects.filter(blog=post)
commentForm = CommentForm()
return render(
request,
'post_detail.html',
{'post': post, 'comments': comments, 'commentForm': commentForm},
)


def comment(request, id):
blog = get_object_or_404(Blog, id=id)
if request.method == 'POST':
commentForm = CommentForm(request.POST)
if commentForm.is_valid():
new_comment = commentForm.save(commit=False)
new_comment.blog = blog
new_comment.author = request.user
new_comment.save()
return redirect('post', id=blog.id)