Easily Convert Django Function Based Views To Class Based Views

In this tutorial I will take a simple notes app built with function based views (FBV) and convert them into class based views (CBV).

This post will be used as a guide for a YouTube tutorial so I recommend watching the full video tutorial and referenci…


This content originally appeared on DEV Community and was authored by Dennis Ivy

In this tutorial I will take a simple notes app built with function based views (FBV) and convert them into class based views (CBV).

This post will be used as a guide for a YouTube tutorial so I recommend watching the full video tutorial and referencing the source code.

Our Function Based Views

Let's start by taking a quick look at the views we currently have.

Our views file has views to follow the basic CRUD operations for Creating, Reading, Updating and Deleting Notes.

def TaskList(request):
    if request.method == 'GET':
        tasks = Task.objects.all().order_by('-updated')
        context = {'tasks':tasks}
        return render(request, 'base/index.html', context)

    if request.method == 'POST':
        task = Task.objects.create(
            body=request.POST.get('body')
        )
        task.save()
        return redirect('tasks')

## ------------------------------------------------------

def TaskDetail(request, pk):
    if request.method == 'GET':
        task = Task.objects.get(id=pk)
        context = {'task':task}
        return render(request, 'base/task.html', context)

    if request.method == 'POST':
        task = Task.objects.get(id=pk)
        task.body = request.POST.get('body')
        task.save()
        return redirect('tasks')

## ------------------------------------------------------

def TaskDelete(request, pk):
    task = Task.objects.get(id=pk)

    if request.method == 'POST':
        task.delete()
        return redirect('tasks')

    context = {'task':task}   
    return render(request, 'base/delete.html', context)

Keeping our class based views raw

Class based views have a level of complexity to them not because they are difficult to use, but because there is a layer of abstraction to them that makes it difficult to understand exactly what's going on and what we need to do to modify them. Django provides us with a number of built in views to use which makes for rapid development, but before you know the ins and outs of the views this can actually make thngs confusing since there is a lot of magic under the hood.

So instead of using the built in views, I will keep things raw and only extend the base view Django gives us and write all the logic from scratch so you can see how class based views compare and differ from function based views.

A few things about class based views

Before we get started there's a few things I want you to know about class based views.

Extending the base View class

Every class based view extends the base View class. Since we are not using any other built in views make sure that you import View and pass in "View" to each class:

from django.views import View
...
class OurView(View):

Separation by http methods

With class based views we separate our code into HTTP verbs. So instead of having to do something like if request.method == 'POST', we simply modify the post method provided by the View class and let that method take care of everything that happens on a post request. The same goes for get requests.

Ex:

class OurView(View):
    def get(self, request):
        pass

    def post(self, request):
        pass

Let's get started with our first view.

TaskList View

Let's comment out the TaskList view and rebuild it from scratch.

We'll rewrite the view as a class now and inherit from the View class. Let's also add two methods to this new class (get & post) and make sure to pass in self before request in each method.

Once we have the class and two methods, lets extract the logic from our function based view and add it to the new class according to each http method like so:

from django.views import View
....
class TaskList(View):

    def get(self, request):
        tasks = Task.objects.all().order_by('-updated')
        context = {'tasks':tasks}
        return render(request, 'base/index.html', context)

    def post(self, request):
        task = Task.objects.create(
            body=request.POST.get('body')
        )
        task.save()
        return redirect('tasks')

Now to use this view we need to reference the class in urls.py and then use the as_view() method.

path('', views.TaskList.as_view(), name="tasks"),

And just like that, we converted our first function based view into a class based view!

TaskDetail View

Now lets do the same for TaskDetail. Again, we will comment out our function based view and extract and separate all the logic we have into the http methods.

class TaskDetail(View):
    def get(self, request, pk):
        task = Task.objects.get(id=pk)
        context = {'task':task}
        return render(request, 'base/task.html', context)

    def post(self, request, pk):
        task = Task.objects.get(id=pk)
        task.body = request.POST.get('body')
        task.save()
        return redirect('tasks')

Then add as_view() to the url path for when we call this view.

path('<str:pk>/', views.TaskDetail.as_view(), name="task"),

TaskDelete View

At this point I'm sure you're starting to see the pattern, so lets do the same as before with the Delete view.

class TaskDelete(View):
    def get(self, request, pk):
        task = Task.objects.get(id=pk)
        context = {'task':task}   
        return render(request, 'base/delete.html', context)

    def post(self, request, pk):
        task = Task.objects.get(id=pk)
        task.delete()
        return redirect('tasks')
path('<str:pk>/delete/', views.TaskDelete.as_view(), name="delete"),

So lets recap what we did.

For each view we:

  • Changed def to class
  • Extended the base View class
  • Separated logic by http methods and added self before request
  • Added as_view() to each view in urls.py


This content originally appeared on DEV Community and was authored by Dennis Ivy


Print Share Comment Cite Upload Translate Updates
APA

Dennis Ivy | Sciencx (2022-07-25T02:44:00+00:00) Easily Convert Django Function Based Views To Class Based Views. Retrieved from https://www.scien.cx/2022/07/25/easily-convert-django-function-based-views-to-class-based-views-2/

MLA
" » Easily Convert Django Function Based Views To Class Based Views." Dennis Ivy | Sciencx - Monday July 25, 2022, https://www.scien.cx/2022/07/25/easily-convert-django-function-based-views-to-class-based-views-2/
HARVARD
Dennis Ivy | Sciencx Monday July 25, 2022 » Easily Convert Django Function Based Views To Class Based Views., viewed ,<https://www.scien.cx/2022/07/25/easily-convert-django-function-based-views-to-class-based-views-2/>
VANCOUVER
Dennis Ivy | Sciencx - » Easily Convert Django Function Based Views To Class Based Views. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2022/07/25/easily-convert-django-function-based-views-to-class-based-views-2/
CHICAGO
" » Easily Convert Django Function Based Views To Class Based Views." Dennis Ivy | Sciencx - Accessed . https://www.scien.cx/2022/07/25/easily-convert-django-function-based-views-to-class-based-views-2/
IEEE
" » Easily Convert Django Function Based Views To Class Based Views." Dennis Ivy | Sciencx [Online]. Available: https://www.scien.cx/2022/07/25/easily-convert-django-function-based-views-to-class-based-views-2/. [Accessed: ]
rf:citation
» Easily Convert Django Function Based Views To Class Based Views | Dennis Ivy | Sciencx | https://www.scien.cx/2022/07/25/easily-convert-django-function-based-views-to-class-based-views-2/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.