Changing View as Generic View in Django

We have only used function-based views so far. I will use class-based generic views in this post. Also there are class-based views and function-based generic views.

Generic views are provides simpler use than normal views. We don't need to defining context, and no need to using render method. Because generic views will do this for us.

Firstly, I'm going to open views.py in the myblog application folder. I will also add a new view, because using two models (post, comment) in a single view is highly discouraged:

from django.db.models.fields import TimeField
from django.http.response import HttpResponseRedirect
from django.shortcuts import redirect, render, get_object_or_404
from django.urls import reverse
from django.views import generic

from .models import Post, Comment


# Create your views here.
class IndexView(generic.ListView):
    model = Post
    context_object_name = 'posts'
    template_name = 'index.html'


class DetailView(generic.DetailView):
    model = Post
    template_name = 'detail.html'

    def get_context_data(self,**kwargs):
        context = super(DetailView,self).get_context_data(**kwargs)
        context['comments']=Comment.objects.all().filter(post = self.kwargs['pk'])
        return context

    def post(self, request, pk):
        post = get_object_or_404(Post, pk=pk)
        new_comment = Comment(
            username= request.POST.get('comment-username'), 
            content= request.POST.get('comment-textarea'),
            post = post
        )
        new_comment.save()
        return redirect(request.META['HTTP_REFERER'])


def about(request):
    return render(request, 'about.html')
I removed comment view because we will use post method from DetailView instead of this view. You can understand why need to use class-based generic view in the above code example. According to views.py, let's edit urls.py:
from django.urls import path
from .views import * 

urlpatterns = [
    path('', IndexView.as_view(), name="index"),
    path('about', about, name="about"),
    path('post/<int:pk>/', DetailView.as_view(), name="detail"),
]
Also change comment form's action like that:
<form action="" method="post">
{% csrf_token %}
<fieldset>
    <legend><h6>Post a comment</h6></legend>
    <label for="usr">username:</label>
    <input type="text" class="form-control" id="usr" name="comment-username">
    <label for="usr">Type your comment:</label>
    <textarea class="form-control" rows="5" id="comment" name="comment-textarea"></textarea>
</fieldset>
<input type="submit" value="Send Comment">
</form>
That's it. We made changings in success. Notes:
  • We overrided get_context_data method to bind comment objects as context.
  • the post method run automatically when the form is submitted.
  • After added new commet object and saved on database, detail page will be refreshed by redirect function with the argument.

No comments:

Post a Comment