Understanding Django Class based views

Aug. 19, 2020

  • server1.jpg Back-End

Class based views are "ready to apply" made views for frequent development situation which don't require the amount of setting necessary to design a functional / classic view.

Below, there are paralled ilustrations of functional views versus class based views.

View

urls
path('my_view/', views.my_view, name='my_view'),
views
#
#
def my_view(request):
    if request.method == 'GET':
        # <view logic> 
        return HttpResponse('result')
template
...

urls
path('my_view_generic/', views.MyView.as_view(), name='my_view_generic'),
views
from django.views import View

class MyView(View):
    def get(self, request):
        # <view logic> 
        return HttpResponse('result')
template
...

Create

urls
path('create_view/',views.create_view, name="create_view"),
views
def create_view(request):

    # add the dictionary during initialization 
    form = GeeksForm(request.POST or None)
    if form.is_valid():
        form.save()

    context ={}
    #reset form fields 
    context['form'] = GeeksForm()

    return render(request, "geeks/create_view.html", context)
template
<form method="POST" enctype="multipart/form-data">

    <!-- Security token -->
    {% csrf_token %}

    <!-- Using the formset -->
    {{ form.as_p }}

    <input type="submit" value="Submit">

</form>

urls
path('create_view_generic/', views.GeeksCreate.as_view(), name="create_view_generic" ),
views
from django.views.generic.edit import CreateView

#default template: geeks/templates/geeks/geeksmodel_form.html
class GeeksCreate(CreateView):

    # specify the model for create view 
    model = GeeksModel

    # specify the fields to be displayed  
    fields = ['title', 'description']

    success_url="/geeks/create_view_generic/"
template
<form method="POST" enctype="multipart/form-data">

    <!-- Security token -->
    {% csrf_token %}

    <!-- Using the formset -->
    {{ form.as_p }}

    <input type="submit" value="Submit">

</form>

Retrieve data:

1) List

urls
path('list_view/',views.list_view, name="list_view"),
views
#
#
def list_view(request):

    context ={}

    # add the dictionary during initialization 
    context["dataset"] = GeeksModel.objects.all()

    return render(request, "geeks/list_view.html", context)
template
{% for data in dataset %}     

  {{ data.title }}<br/>  
  {{ data.description }}<br/>  
  <hr/>   

  <!-- If dataset is empty  -->
  {% empty %}
  <li>No objects yet.</li>  

{% endfor %}

urls
path('list_view_generic/', views.GeeksList.as_view(), name="list_view_generic"),
views
from django.views.generic.list import ListView

#default template : geeks/templates/geeks/geeksmodel_list.html
class GeeksList(ListView):

    #modify default context_object_name
    #context_object_name = 'all_geeks_list'

    # specify the model for list view 
    model = GeeksModel
template
{% for object in object_list %}

  {{ object.title }}<br/> 
  {{ object.description }}<br/>
  <hr/>

  <!-- If objet_list is empty  -->
  {% empty %}
  No objects yet.

{% endfor %}

2) Detail

urls
path('detail/<int:id>/', views.detail_view, name="detail" ),
views
def detail_view(request, id):

    context ={}

    context["data"] = GeeksModel.objects.get(id = id)

   return render(request, "geeks/detail_view.html", context)
template
{{ data.title }}<br/>
{{ data.description }}<br/>

urls
path('detail_generic/<int:pk>/', views.GeeksDetailView.as_view(), name="detail_generic"),
views
#
from django.views.generic.detail import DetailView

#default template: geeks/templates/geeks/geeksmodel_detail.html
class GeeksDetailView(DetailView):
    # specify the model to use
    model = GeeksModel
template
<h1>{{ object.title }}</h1>
<p>{{ object.description }}</p>

Update

urls
path('update/<int:id>/', views.update_view, name="update"),
views
def update_view(request, id):
    context ={}

    # fetch the object related to passed id 
    obj = get_object_or_404(GeeksModel, id = id)

    # pass the object as instance in form 
    form = GeeksForm(request.POST or None, instance = obj)

    # save the data from the form and 
    # redirect to detail_view 
    if form.is_valid():
        form.save()
        return HttpResponseRedirect("/geeks/detail/"+str(id))

    # add form dictionary to context 
    context["form"] = form

    return render(request, "geeks/update_view.html", context)
template
<form method="POST">

        <!-- Security token by Django -->
        {% csrf_token %}

        <!-- form as paragraph -->
        {{ form.as_p }}

        <input type="submit" value="Update">

</form>

urls
path('update_generic/<int:pk>/', views.GeeksUpdateView.as_view(), name="update_generic"),
views
#
#
#
#
from django.views.generic.edit import UpdateView

#default template_name : geeks/templates/geeks/geeksmodel_form.html
class GeeksUpdateView(UpdateView):
    # specify the model you want to use 
    model = GeeksModel

    # specify the fields 
    fields = [
        "title",
        "description"
    ]

    def get_success_url(self):
        return f"/geeks/detail/{self.object.pk}"
template
<form method="POST" > 

    <!-- Security token -->
    {% csrf_token %}

    <!-- Using the formset -->
    {{ form.as_p }}

    <input type="submit" value="Submit">

</form>

Delete

urls
path('delete/<int:id>/', views.delete_view, name="delete" ),
views
def delete_view(request, id):
    context ={}

    # fetch the object related to passed id 
    obj = get_object_or_404(GeeksModel, id = id)

    if request.method =="POST":
        # delete object 
        obj.delete()
        # after deleting redirect to  
        # home page 
        return HttpResponseRedirect("/geeks/list_view/")

    return render(request, "geeks/delete_view.html", context)
template
<form method="POST">
        <!-- Security token by Django -->
        {% csrf_token %}
        Are you sure you want to delete this item ?
        <input type="submit" value="Yes" />
        <a href="/geeks/">Cancel </a>
    </form>

urls
path('delete_generic/<int:pk>/', views.GeeksDeleteView.as_view(), name="delete_generic"),
views
#
#
#
from django.views.generic.edit import DeleteView

#default template_name : geeks/templates/geeks/geeksmodel_confirm_delete.html
class GeeksDeleteView(DeleteView):
    # specify the model you want to use 
    model = GeeksModel

    # can specify success url 
    # url to redirect after successfully 
    # deleting object 
    success_url ="/geeks/list/"
template
<form method="post">
    <!-- Security token by Django -->
    {% csrf_token %}
    <p>Are you sure you want to delete "{{ object }}"?</p>
    <input type="submit" value="Confirm">
    <a href="/geeks/">Cancel </a>
</form>

Some methods for customizing class based views:

  • get_context_data() for defining additional context data for template
  • queryset
  • get_query_set() for customizing query
class GeeksCreate(CreateView):

    # specify the model for create view 
    model = GeeksModel

    # specify the fields to be displayed  
    fields = ['title', 'description']

    success_url="/geeks/create_view_generic/"

    #aditional context data, if needed
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['success'] = "True"
        return context
class GeeksList2(ListView):

    context_object_name = 'selected_geeks_list'
    queryset = GeeksModel.objects.filter(title__startswith='book')
    template_name = 'geeks/geeks_by_title.html'

class GeeksList3(ListView):

    template_name = 'geeks/geeks_by_description.html'

    def get_queryset(self):
        return Book.objects.filter(description__contains="motorcycle")

Examples are inspired by a geeksforgeeks article and are available at django_tutorial git repo.


Return to home