Django's Class-Based-Views inheritance

Python Django

Lately, I've been moving away from django's Function-Based-Views (FBV) to Class-Based-Views (CBV) (which, by the way, are awesome and I recommend you to use it) and I found my self keep overiding the get_context_data() (who's job is to return the context dict which will be used in the template) method.

Since the big advantage of using CBV's over FBV's are inheritance, we could eliminate the code repetition I had in my get_context_data()

Solution

This class CourseContextMixin() is the class I'm going to inherit from for my other views, so that they'll all use the same get_context_data(). In my case, I wanted to pass the profile variable which contains information about the signed in user to the template.


# Base class which my other views will inherit
class CourseContextMixin(ContextMixin, View): # since I need the request param, I'm including the View class
    def get_context_data(self, **kwargs):
        context = super(CourseContextMixin, self).get_context_data(**kwargs)
        profile = get_object_or_404(Profile, user__username=self.request.user)
        context['profile'] = profile
        return context


All my other views now will inherit CourseContextMixin and will not need to override the get_context_data() method.



@method_decorator(login_required, name='dispatch')
class CourseDetailView(CourseContextMixin, DetailView):
    model = Course
    template_name = 'course_detail.html'

    def get_queryset(self):
        slug = self.kwargs.get('slug', None)
        abbrv = self.kwargs.get('abbreviation', None)
        number = self.kwargs.get('number', None)
        profile = get_object_or_404(Profile, user__username=self.request.user)
        return super(CourseDetailView, self).get_queryset().filter(instructor=profile,
                                                                   slug=slug,
                                                                   abbreviation=abbrv,
                                                                   number=number,
                                                                   )


@method_decorator(login_required, name='dispatch')
class CourseListView(CourseContextMixin, ListView):
    model = Course
    template_name = 'course_list.html'

    def get_queryset(self):
        profile = get_object_or_404(Profile, user__username=self.request.user)
        return super(CourseListView, self).get_queryset().filter(instructor=profile)


@method_decorator(login_required, name='dispatch')
class CourseCreateView(CourseContextMixin, CreateView):
    model = Course
    template_name = 'course_form.html'
    success_url = reverse_lazy('course-create-complete')
    form_class = CourseForm
    object = None

    def form_valid(self, form):
        self.object = form.save(commit=False)
        instructor = get_object_or_404(Profile, user__username=self.request.user)
        self.object.instructor = instructor
        self.object.save()
        return HttpResponseRedirect(self.get_success_url())


Thanks for reading! and let me know if you have any feedback.

© 2017 Mustafa Abualsaud. All rights reserved.