YouTip LogoYouTip

Django Blog Cbv

In this chapter, you will learn Django's Class-Based Views (CBV) to refactor the homepage and detail page with more concise code. * * * ## FBV vs CBV So far, all our views have been written using functions (Function-Based View, FBV). Django also provides Class-Based Views (CBV), which encapsulate view logic in classes. | Feature | FBV (Function-Based View) | CBV (Class-Based View) | | --- | --- | --- | | Code Amount | Flexible, but common logic needs to be repeated | After inheriting generic views, only a few lines of code needed | | Readability | Linear flow, clear logic | Inheritance chain needs to be traced, but becomes clear once familiar | | Reusability | Encapsulated through functions | Combined through Mixins (Django's feature) | | Applicable Scenarios | Pages with simple logic and clear flow | Standard CRUD pattern pages | | HTTP Method Dispatch | Manual if request.method == 'POST' | Automatic dispatch to get() / post() methods | There is no absolute advantage or disadvantage between the two. Django projects typically use a mix of FBV and CBV: FBV for complex logic, CBV for standard CRUD operations. * * * ## ListView β€” List Page Refactoring The homepage's index view essentially does: query article list β†’ render template. For this kind of standardized logic, Django's `ListView` has already been written for you. ## Example # File path: blog/views.py from django.views.generic import ListView from django.db.models import Q from .models import Post, Category class PostListView(ListView): """Blog homepage: inherits ListView, displays article list""" model = Post # Specify model template_name ='blog/index.html'# Specify template (default: blog/post_list.html) context_object_name ='posts'# Variable name used in template (default: object_list) paginate_by =12# 12 items per page (pagination) ordering =['-created_at']# Ordering def get_queryset(self): """Override query method: support category filtering + keyword search""" queryset =super().get_queryset() # Category filtering self.category_slug=self.request.GET.get('category','') if self.category_slug: queryset = queryset.filter(category__slug=self.category_slug) # Keyword search self.keyword=self.request.GET.get('q','') if self.keyword: queryset = queryset.filter( Q(title__icontains=self.keyword) | Q(summary__icontains=self.keyword) ) return queryset def get_context_data(self, **kwargs): """Override context method: inject additional data into template""" context =super().get_context_data(**kwargs) context['categories']= Category.objects.all() context['category_slug']=self.category_slug context['keyword']=self.keyword context['title']='TUTORIAL Home - Home' return context Compare the code amount before and after refactoring: FBV ~40 lines β†’ CBV ~30 lines, and the logic is clearly divided into different methods. * * * ## DetailView β€” Detail Page Refactoring ## Example # File path: blog/views.py Add new from django.views.generic import DetailView class PostDetailView(DetailView): """Article detail page: inherits DetailView""" model = Post template_name ='blog/post_detail.html' context_object_name ='post' # pk_url_kwarg: parameter name for primary key passed in URL (default is pk, explicitly declared here) pk_url_kwarg ='pk' def get_context_data(self, **kwargs): context =super().get_context_data(**kwargs) context['title']= f'{self.object.title} - TUTORIAL Home' return context * * * ## Update URL Configuration The CBV routingway of writing is slightly different from FBV β€” you need to call `.as_view()`. ## Example # File path: blog/urls.py from django.urls import path from django.contrib.auth import views as auth_views from . import views urlpatterns =[ # CBV: add .as_view() after the class to convert it to a view function path('', views.PostListView.as_view(), name='index'), path('post//', views.PostDetailView.as_view(), name='post_detail'), # Other views remain unchanged path('register/', views.register, name='register'), path('login/', auth_views.LoginView.as_view( template_name='blog/login.html', redirect_authenticated_user=True ), name='login'), path('logout/', auth_views.LogoutView.as_view(), name='logout'), path('post//favorite/', views.toggle_favorite, name='toggle_favorite'), ] > Why does CBV use `.as_view()`? Django's URL configuration expects a callable (function). `.as_view()` converts the class-based view into a callable that conforms to Django's view function signature, internally responsible for automatically dispatching based on HTTP methods (GET/POST) to the class's get() or post() methods. * * * ## Common Generic Views Overview | View | Default Template Name | Purpose | | --- | --- | --- | | ListView | modelname_list
← Flask Blog Project InitDjango Blog Auth β†’