Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.4k views
in Technique[技术] by (71.8m points)

django - Provide extra context to all views

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.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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>

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...