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, callis_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:
signupForm = SignUpForm()
return render(request, 'signup.html', {'signupForm': signupForm})
and a POST request binds the submitted data, validates it and saves the new user:
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.
I will create html files in later topics.
Login Form
In signin() in views.py, a GET request renders an empty LoginForm:
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:
blogForm = BlogForm()
return render(request, 'create_post.html', {'postForm': blogForm})
On POST, note two details:
blogForm = BlogForm(request.POST, request.FILES)
if blogForm.is_valid():
blog = blogForm.save(commit=False)
blog.author = request.user
blog.save()
request.FILESmust be passed as well, because the form contains anImageField.save(commit=False)returns an unsavedBloginstance so the view can attachauthor(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:
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:
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)