Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Provide extra context to all views

Tags:

I'm putting together a project management website for my team using django. My base template includes a sidebar menu which contains a list of all projects and users, linking to a DetailView for that user or project, respectively.

My problem is that I need to provide the User and Project models to every view so that I can render that sidebar. I know how to add extra context; the problem is that I feel like I'm violating DRY by modifying the context at each level. Is it possible to simply redefine the base TemplateClass so that all child classes—ListView, DetailView, etc.—contain the modified context?

On a related note, if this is a terrible way to set up the project, let me know that as well.

like image 362
eykanal Avatar asked Feb 16 '15 02:02

eykanal


People also ask

How do you pass context in class based view?

Passing context into your templates from class-based views is easy once you know what to look out for. There are two ways to do it – one involves get_context_data, the other is by modifying the extra_context variable. Let see how to use both the methods one by one.

What is context in Django view?

A context is a variable name -> variable value mapping that is passed to a template. Context processors let you specify a number of variables that get set in each context automatically – without you having to specify the variables in each render() call.

What is a template context?

The context template data file provides the content for establishing the context. It is usually a JAR or ZIP file that contains a specification XML file, the template DTD, business XML files for defining rules, and content files for any objects that are identified in the specification.

What is Django generic views?

Django's generic views were developed to ease that pain. They take certain common idioms and patterns found in view development and abstract them so that you can quickly write common views of data without having to write too much code.


1 Answers

You could use the template context processor:

myapp/context_processors.py:

from django.contrib.auth.models import User from myapp.models import Project  def users_and_projects(request):     return {'all_users': User.objects.all(),             'all_projects': Project.objects.all()} 

And then add this processor to the TEMPLATE_CONTEXT_PROCESSORS setting for Django version < 1.8:

TEMPLATE_CONTEXT_PROCESSORS = (     ...     'myapp.context_processors.users_and_projects', ) 

And for Django version >= 1.8 add it to the context_processors list in the OPTIONS of the TEMPLATES setting:

TEMPLATES = [     {         ...         'OPTIONS': {             'context_processors': [                 ...                 'myapp.context_processors.users_and_projects',             ],         },     }, ] 

Context processor will run for ALL your requests. If your want to run these queries only for views which use the base.html rendering then the other possible solution is the custom assignment tag:

@register.assignment_tag def get_all_users():     return User.objects.all()  @register.assignment_tag def get_all_projects():     return Project.objects.all() 

And the in your base.html template:

{% load mytags %}  {% get_all_users as all_users %} <ul> {% for u in all_users %}     <li><a href="{{ u.get_absolute_url }}">{{ u }}</a></li> {% endfor %} </ul>  {% get_all_projects as all_projects %} <ul> {% for p in all_projects %}     <li><a href="{{ p.get_absolute_url }}">{{ p }}</a></li> {% endfor %} </ul> 
like image 156
catavaran Avatar answered Oct 19 '22 23:10

catavaran