haki
haki

Reputation: 9779

Django - update custom context in view

I have a custom context processor that passes some server side constants to the client (by injecting into javascript object). Some views might want to add additional params, notifications for example, to the dict.

from django.contrib.sites.shortcuts import get_current_site

def client_context(request):
    params = {}

    domain = get_current_site(request).domain
    schema = request.scheme
    params['rooturl'] = "%s://%s" % (schema,domain)

    return {'params': params}

According to the docs

When context processors are applied

Context processors are applied after the context itself is processed. This means that a context processor may overwrite variables you’ve supplied to your Context or RequestContext, so take care to avoid variable names that overlap with those supplied by your context processors.

If I render a template without overriding params it's working fine - i get the baseurl in the template.

If I render the template with a variable named params i get only the overrided value.

def home(request):  
    return render(request, 'home.html', { 'params' : {'page' : 'home'} })

so i have two questions

  1. Is the django docs incorrect ? from what i understand the second dict should update the first one. According to these findings my custom context is applied first.

  2. What is the best way to achieve this ?

EDIT

In my base.html file (extended by all other templates) i pass the params object to a Js objects. e.g

{% block init %}
<script>
   Global = new Global( {{ params | json }} );
</script>
{% endblock %}

I was hoping for a solution that wont require adding each possible parameter by name

{% block init %}
<script>
   Global = new Global( { baseurl : "{{baseurl}}", page : "{{ page }}" );
</script>
{% endblock %}

Upvotes: 1

Views: 3099

Answers (1)

Alasdair
Alasdair

Reputation: 309039

Django is working as documented. The params returned by your template context processor is overwriting the params in the view's context. Django doesn't automatically merge dictionaries as you want.

Instead of using the render shortcut, you could make your views return TemplateResponse objects. Then, instead of writing a context processor, write a middleware that updates the params dict in the process_template_response method.

Upvotes: 1

Related Questions