Jobo Fernandez
Jobo Fernandez

Reputation: 901

How can I efficiently factor out similar contexts from multiple views in Django?

Suppose we have two or more views, where each view templates extends from base.html, and inside the base.html file are context variables project_name and company_name:

File base.html

<!DOCTYPE html>
<html>
  <head>
    <title>{{ project_name }}</title>
  </head>
  <body>
    {{ company_name }}
    {% block content %}{% endblock %}
  </body>
</html>

Then we would have to add the above-mentioned contexts to our views as follow:

File views.py

def view1(request)
    context = {
        "view1 data": "some data",
        "project_name": "Project Name",
        "company_name": "Company Name",
    }
    return render(request, "view1.html", context)


class View2(DetailView):
    template_name = "view2.html"
    model = SampleModel

    def get_context_data(self, **kwargs):
        context = super(View2, self).get_context_data(**kwargs)
        context["view2 data"] = "sample data"
        context["project_name"] = "Project Name"
        context["company_name"] = "Company Name"
        return context

How do we write an efficient code so that our views will look like as follows, i.e. the common contexts project_name and company_name are factored out somewhere else yet will still be displayed in the base.html?

Desired views.py

def view1(request)
    context = {
        "view1 data": "some data",
    }
    return render(request, "view1.html", context)


class View2(DetailView):
    template_name = "view2.html"
    model = SampleModel

    def get_context_data(self, **kwargs):
        context = super(View2, self).get_context_data(**kwargs)
        context["view2 data"] = "sample data"
        return context

Understandably, function-based views and class-based views may function differently so there may be different solutions to each of them.

Upvotes: 0

Views: 142

Answers (1)

mubtasimfuad
mubtasimfuad

Reputation: 173

To my knowledge, I know there are approaches to achieve that more efficiently. But adding a context processor is the efficient for me.

So, the following code snippet will make you understand the process:

Create a new Python file in any of your app folders; preferably name it as 'context_processors.py'. In that 'context_processors.py' file you may write:

def any_function_name(request):
    any_dictionary_name = {
        "view1 data": "some data",
        "project_name": "Project Name",
        "company_name": "Company Name",
    }

    return any_dictionary_name

(Note: Like that, you can even write queryset to get any data and make it available globally)

Then go the main project's file settings.py add the reference of your context processors:

TEMPLATES = [
    {
        "BACKEND": "django.template.backends.django.DjangoTemplates",
        'DIRS': [],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
                'your_app_name.context_processors.any_function_name' #Add the file reference here
            ],
        },
    },
]

Afterwards, you can access your context data anywhere in the template like this:

<!DOCTYPE html>
<html>
    <head>
        <title>{{ project_name }}</title>
    </head>

    <body>
      {{ company_name }}
      {% block content %}{% endblock %}
    </body>
</html>

Upvotes: 3

Related Questions