Adding frequently used context objects to a view in Django

I have several Django apps within a single project. What I am running into is that I often tend to add the same object(s) to the render call that renders a particular screen.

In this example below, I have a view that displays a form with a dropdown of categories that you can choose from. Now I need to add these categories every time I display the create.html page. This is simplified, but imagine I have 6 more views that could potentially show the create.html page, all of them have to remember to add the categories array.

    def createmeeting(request):
        if request.method == "POST":

            categories = MeetingCategory.objects.all()

            // Some error checking, omitted for this example
            error_msg = "invalid content"

            if error_msg:
                return render(request, "meetings/create.html",
                    {
                        "categories":               categories,
                        "error_msg":                error_msg,
                     })
            else:
                // Create the meeting here, omitted for this example
                return redirect("/meetings/profile/")
        else:
            categories = MeetingCategory.objects.all()
            return render(request, "meetings/create.html",
                {
                    "categories": categories
                })

Is there a better way of handling cases like this?

You could create a context processor that will add the context to all views in your app like here: https://docs.djangoproject.com/en/5.0/ref/templates/api/#writing-your-own-context-processors

You could always add an if statement: if request.path.startswith(("path1", "path2", "xxx")) to prevent it being added to all views

If you go over to using class-based views, you can put the common code into a Mixin class. The Mixin class would look like this:

class MeetingCategoriesMixin( object):
    def get_context_data( self, **kwargs):
        context = super().get_context_data( **kwargs)
        context['categories'] =  MeetingCategory.objects.all()
        return context

and your view (which could be a FormView or UpdateView or CreateView or even just a TemplateView)

class MyViewWithCategories( MeetingCategoriesMixin, FormView):
     form_class = MyFormClass
     template_name = 'meetings/create.html'
     def get_success_url(self):
         return reverse( 'meetings:profile', kwargs={ ...})
     def form_valid( self, form):
         # use the valid data in the form here

         # return super().form_valid( form) # or I prefer explicitly,
         return HttpResponseRedirect( self.get_success_url() )
         

My opinionated view is to use function-based views only for cases where a standard class-based view really is too hard (and note that if you are processing a form, you can do absolutely anything in form_valid() )

( Semi-obligatory plug for classy class-based views )

Back to Top