To all of the Django devs struggling with Class-Based Views (CBVs)…

I've seen a lot of people on here and /r/django struggling with CBVs recently.

Just a reminder that you \*do not\* need to feel obligated to use CBVs. In real-world projects, the ratio of [FBV](https://docs.djangoproject.com/en/3.2/topics/http/views/)\-to-[CBV](https://docs.djangoproject.com/en/3.2/topics/class-based-views/intro/) is [essentially 50/50](https://dev.to/jackdlinke/modern-django-project-examples-58mm). CBVs are not objectively better or worse than FBVs, but they can be very difficult, especially for beginners. If you are struggling with CBVs, there are a couple things to consider:

* First, if do you choose to use CBVs there is a very detailed resource for familiarizing yourself with their intricacies: [https://ccbv.co.uk/](https://ccbv.co.uk/)
* Second, there is nothing unusual about struggling a bit with CBVs. They really can be complicated. Consider using FBVs to start with until you get more experience, or even skipping CBVs altogether (except if you're using DRF's ViewSet, for instance). I encourage you all to read through this excellent guide by [Luke Plant](https://twitter.com/spookylukey?lang=en) (one of Django's core developers) about why FBVs may be the better approach to Django Views. Even if you don't completely agree, he provides a number of useful insights and advice: [https://spookylukey.github.io/django-views-the-right-way/](https://spookylukey.github.io/django-views-the-right-way/)

11 thoughts on “To all of the Django devs struggling with Class-Based Views (CBVs)…”

  1. That’s a great guide, thanks for sharing.

    I’m curious for examples of situations where using a CBV is the best solution?

    I’ve always found FBVs the most intuitive, but the prevalence of CBVs makes me think I’m missing something.

    Reply
  2. Can CBVs be used for generic functionality and FBVs used for the more bespoke functionality? Or are there CBVs, that can be adapted, for every operation a website needs? Excellent website link thanks.

    Reply
  3. Also, in case it helps anyone else, I keep this list of very simple FBV view starters handy in my notes. I’m sure it’s imperfect, but feel free to adapt to your needs:

    views.py

    from django.shortcuts import render
    from django.shortcuts import get_object_or_404, HttpResponseRedirect
    from django.template.response import TemplateResponse

    from .forms import MyModelForm
    from .models import MyModel

    def create_view(request):
    template = “create_view.html”
    context = {}

    form = MyModelForm(request.POST or None)
    if request.method == ‘POST’:
    if form.is_valid():
    form.save()

    return HttpResponseRedirect(‘/thanks/’)

    context[“form”] = form
    return TemplateResponse(request, template, context)

    def list_view(request):
    template = “list_view.html”
    context = {}

    context[“dataset”] = MyModel.objects.all()

    return TemplateResponse(request, template, context)

    def detail_view(request, id):
    template = “detail_view.html”
    context = {}

    context[“data”] = MyModel.objects.get(id=id)

    return TemplateResponse(request, template, context)

    def update_view(request, id):
    template = “update_view.html”
    context = {}

    obj = get_object_or_404(MyModel, id=id)
    form = MyModelForm(request.POST or None, instance=obj)

    if form.is_valid():
    form.save()
    return HttpResponseRedirect(“/” + id)

    context[“form”] = form

    return TemplateResponse(request, template, context)

    def delete_view(request, id):
    template = “delete_view.html”
    context = {}

    obj = get_object_or_404(MyModel, id=id)

    if request.method == “POST”:
    obj.delete()
    return HttpResponseRedirect(“/”)

    return TemplateResponse(request, template, context)

    def htmx_example_view(request, arg):
    template = “fragments/example.html”

    context = {}
    context[“key”] = “value”

    return TemplateResponse(request, template, context)

    def htmx_example_view2(request, arg):
    “””if using django-htmx”””
    if request.htmx:
    template = “partial.html”
    else:
    template = “complete.html”

    context = {}
    context[“key”] = “value”

    return TemplateResponse(request, template, context)

    def paginated_list_view(request):
    contact_list = Contact.objects.all()
    paginator = Paginator(contact_list, 25) # Show 25 contacts per page.

    page_number = request.GET.get(‘page’)
    page_obj = paginator.get_page(page_number)
    return render(request, ‘list.html’, {‘page_obj’: page_obj})

    Reply
  4. That Luke Plant blog post was a real game changer for me and allayed lots of paranoia I had that using FBV was somehow “not the proper way” or more amateurish…

    I also found the predecessor to that post helpful: https://lukeplant.me.uk/blog/posts/my-approach-to-class-based-views/, which could be summarised as “if you don’t like GCBVs, write your own base Classes”.

    Every Django begginer tutorial for a while was “start with FBV and then graduate to CBV”, and now there seems to be more growing consensus that either is fine (as mentioned by OP). I wonder if this is because of the rise of Flask/FastAPI…?

    Reply
  5. HaHa. I logged in today just because the docs for Class Based views seem loaded with info while not answer most of my questions. But its just me for now.

    Reply
  6. Is it bad practice to mix both CBV and FBV in your app? I usually use CBV for simple GET requests but for POST or DELETE requests, I use FBV.

    Reply
  7. ive read python crash courses whole all chapters but the last one and it was fbv then i started to read django for begginers by williams vincent and its cbv

    idk should i read it or no becuz its really harder but kinda it feels more updated

    and if no then what should i read

    Reply
  8. I didn’t find Luke Plant’s guide useful. It felt biased towards FBV rather than a fair comparison of each one advantages and uses.

    Reply

Leave a Comment