Django Blog #24: Creating and Processing Forms from Models

by Alex
Django Blog #24: Creating and Processing Forms from Models
Still need a form for users to comment on posts. Django has two basic classes for building forms: Form and ModelForm. The first one was already used to allow users to share posts via email. Now you need to use ModelForm because the form needs to be created dynamically based on Comment. Edit the blog application’s forms.py file and add the following lines:

from .models import Comment

class CommentForm(forms.ModelForm) 
   class Meta 
        model = Comment  
        fields = ('name', 'email', 'body')

To create a model-based form, you just need to specify which model to take as the basis in the Meta form class. Django examines the model and builds the form dynamically. Each field in the model has a corresponding default form field type. The way the model fields have been defined is taken into account when validating the form. By default, Django creates a form field for each model field. But you can explicitly tell the framework which fields are needed in the form by using the fields list or defining which fields to exclude by using the exclude fields list. For the CommentForm, name, email, and body will be used because that’s the only thing that needs to be filled in.

Processing ModelForms in views

For simplicity, the post view will be used to create the form instance and process it. Edit the views.py file, add imports for the Comment model and CommentForm, and edit the post_detail view to look like this:

from .models import Post, Comment 
from .forms import EmailPostForm, CommentForm

def post_detail(request, year, month, day, post) 
    post = get_object_or_404(Post, slug=post,  
				   status='published',  
				   publish__year=year,  
				   publish__month=month,  
				   publish__day=day) 
      
# list of the active comments on this post 
comments = post.comments.filter(active=True)
    new_comment = None 
   if request.method == 'POST' 
       # The comment has been posted
	comment_form = CommentForm(data=request.POST) 
       if comment_form.is_valid() 
           # Create a Comment object, but don't save it to the database yet
	    new_comment = comment_form.save(commit=False) 
           # Assign the current post to the comment
	    new_comment.post = post  
           # Save comment in the database 
 	    new_comment.save() 
    else 
        comment_form = CommentForm() 
   return return(request,  
		 'blog/post/detail.html',  
		 {'post': post,  
'comments': comments,
		  { 'new_comment': new_comment,  
		 'comment_form': comment_form})

Let’s break down what’s in the view. The post_detail view is used to display the post and comments. Use QuerySet to retrieve all active comments:

comments = post.comments.filter(active=True)


This QuerySet starts with the post object. The manager for related objects defined in comments is used with the related_name attribute of the relationship in the Comment model. The same view is used to allow users to leave comments. The new_comment variable is initialized by passing it the value None. It is created when the comment is created. An instance of the form is created with comment_form = CommentForm() if the view is called with a GET request. If it is done via POST, the form instance is created with the submitted data and is validated via the is_valid() method. If the form is invalid, a template with validation errors is rendered. If the form is correct, the following steps are performed:

  1. A new Comment object is created by calling the form’s save() method and assigning it to the new_comment variable as follows:
    new_comment = comment_form.save(commit=False)

    The save() method creates an instance of the model to which the form is attached and saves it to the database. If it is called with commit=False, an instance will be created, but saving to the database will not take place. This is handy when you want to change the object before saving. And this is the next step. The save() method is available for ModelForm, but not for Form instances because they are not bound to any model.

  2. The current post is assigned to the created comment:
    new_comment.post = post

    This marks the comment as belonging to that post.

  3. Finally, the new comment is saved to the database via the save() method:
    new_comment.save()

The view is ready to display and process new comments.

Related Posts

LEAVE A COMMENT