Is there any solution for setting some variables accessible in all templates without setting parameters in each views?
For example, if I login the system, the var = 1, and all templates can use var value.
(pre note: it is a good practice to always use these RequestContexts even if you don't need global data YET, because you never know if, upon a change, you will need global data later).
Use a Template Context Processor and use RequestContexts for each of your templates when you return from your views. When you send a RequestContext(request) as context for your templates inside your views, they will have all the data provided for each registered Context Processor.
e.g. consider this view:
def some_view(request):
# ...
c = RequestContext(request, {
'foo': 'bar',
}, [ip_address_processor])
return HttpResponse(t.render(c)) #or use render_to_resonse('yourtemplate', c)
if you had a context processor like:
def foos(request):
return {'var': 1} #this is the data this CP provides to each of your requests.
#yes, data must be a dict-like object.
you will have var as a variable in every request, in every template using RequestContext(request). Your prev. view would have both foo and var variables available (passing a dict-like argument as the second parameter for RequestContext is like passing that value directly to the render method or the render_to_response shortcut function; using the RequestContext(request, data) let's you enjoy all the data provided by your context processors).
If you use Django's Class-based views or the render() shortcut (and not the render_to_response shortcut), a RequestContext instance will automatically be used as the context.
REMEMBER that you must APPEND to the default values, instead of overriding the tuple. e.g.:
TEMPLATE_CONTEXT_PROCESSORS = ("django.contrib.auth.context_processors.auth",
"django.core.context_processors.debug",
"django.core.context_processors.i18n",
"django.core.context_processors.media",
"django.core.context_processors.static",
"django.core.context_processors.tz",
"django.contrib.messages.context_processors.messages",
"path.to.foos")
in your settings.py file (all but the last, are the default context processors used in django 1.5). Otherwise you'd be losing most of the required CPs by the django core or many packages (yes, IMHO an ugly caveat, but if you override you must specify the default ones as well)
Related
I have the following function that I call in all of my apps and in almost every view function.
def get_customer(request):
return request.user.customer
I want to have one function that I can call from every app or even have this value available in every view.
How can I do this?
I am not really sure how you want to use, but if you need something reusable mostly for templates (as views handle logic differently depending on the request) then you can proceed with the bellow method, if you need something reusable in different parts of the stack, then a simple function / class that is imported in the appropriate parts is just enough.
If you want to inject a reusable var inside the view, then a context.processor is the good place to have this kind of logic.
create a context_processors.py file (name does not matter, but it's always nice to follow Django naming schemes for readability) in one of your apps (most likely the app that deals mostly with the logic, probably the customer app).
In your context_processors.py:
def get_customer(request):
try:
customer = request.user.customer
return {'customer': customer}
except:
"""
You need to always return a dictionary, even empty.
"""
return {}
Enable the context processor, in your TEMPLATE_CONTEXT_PROCESSORS (settings.py):
TEMPLATE_CONTEXT_PROCESSORS = (
"django.contry.context_processors.request",
"django.contrib.auth.context_processors.auth",
"django.core.context_processors.debug",
"django.core.context_processors.i18n",
"django.core.context_processors.media",
"django.core.context_processors.static",
"django.core.context_processors.tz",
"django.contrib.messages.context_processors.messages"
"yourapp.context_processors.get_customer"
)
THen in your template you can access this:
{% if customer %}
...
{% endif %}
Mind though that is wise to create names that wont conflict with other parts, so it would be better to name the passed element
to something more unique like myappscustomer.
If you are using CBV's (Class Based Views) you could create a Mixin and reuse it:
class MyCustomerMixin(object):
def get_context_data(self, **kwargs):
context = super(MyCustomerMixin, self).get_context_data(**kwargs)
if self.request.user:
try:
context['mycustomer'] = self.request.user.customer
except:
pass
return context
Then use it in your View:
class SomeView(MyCustomerMixin, TemplateView):
....
Following the docs
If TEMPLATE_CONTEXT_PROCESSORS contains this processor, every
RequestContext will contain these variables:
user – An auth.User instance representing the currently logged-in user
(or an AnonymousUser instance, if the client isn’t logged in). perms –
An instance of django.contrib.auth.context_processors.PermWrapper,
representing the permissions that the currently logged-in user has.
I added these lines to settings.py
TEMPLATE_CONTEXT_PROCESSORS = (
"django.contrib.auth.context_processors.auth",
)
Rendering my templates as follows
def profile_view(request):
return render_to_response('profile.html', { 'profile' : 1 })
I was under the impression that the request context along with the user will be passed automatically. Is that not the case, or should i explicitly add context_instance=template.RequestContext(request)) to every view ?
Thanks.
Yes, if you want to use render_to_response and you want template context data available, you should pass in a RequestContext instance.
Alternatively, if you render your page with django.shortcuts.render, the RequestContext will be injected automatically.
You may find this answer useful, too: Django - what is the difference between render(), render_to_response() and direct_to_template()?
I need to get an environment variable (ex: Mixpanel_Token) in all my templates, and without creating a new view in Django.
From what I read on SO, I should use a Template Context Processor.
The context_processor is defined in context_processors.py file:
from django.conf import settings
def settings_mixpanel(request):
ctx = {
"MIXPANEL_TOKEN": settings.MIXPANEL_TOKEN,
}
return ctx
In my settings.py file:
TEMPLATE_CONTEXT_PROCESSORS = (
'utils.context_processors.settings_mixpanel',
)
The issue I encounter is how to define MIXPANEL_TOKEN as a context variable in all my templates, given that all my views are already created in Django.
I don't want to recreate a view like the below one, using render_to_response function:
def index(request):
return render_to_response("index.html", {},context_instance=RequestContext(request))
You don't need to do anything special. As long as your template is rendered with RequestContext, you'll be able to access your variable with {{ MIXPANEL_TOKEN }}.
It is quite easy and straightforward: the context processors are called by RequestContext(...). If you do not use RequestContext(...), the context processors will not be used and will therefore not be of any value. You do not necessarily need to use render_to_response, but RequestContext is a must. Like it or not, that is how Django works. But from my personal view, changing your existing views to use RequestContext is not really a big thing, is it?
since Django 1.8 registring of custom context processor for templates happens via: TEMPLATES-> OPTIONS -> context_processors see here for reference: https://docs.djangoproject.com/en/1.10/ref/templates/upgrading/#the-templates-settings
In my view, if I specify
def myView(request):
return render_to_response('myTemplate.html', {'user': request.user,},
context_instance=RequestContext(request))
then I can access settings such as STATIC_URL in myTemplate.html.
However, if I specify
def myView(request):
return render_to_response('myTemplate.html', {'user': request.user,})
then I cannot access STATIC_URL. In this latter case, {{ STATIC_URL }} just yields an empty string in the rendered page. In the former case, {{ STATIC_URL }} yields the proper string for the static URL ("/static/").
Why do I need to send a request context to access the STATIC_URL setting in my template?
I am running Django 1.4 on Apache 2.
Read the docs for a better answer. But there is the short answer:
This is because of DRY (Don´t Repeat Yourself), think this: what if you need set the same variable in all the templates through all the views?: context_processors, are methods that add variables to your templates in a more ordered way.
I quote:
Django comes with a special Context class, django.template.RequestContext, that acts slightly differently than the normal django.template.Context. The first difference is that it takes an HttpRequest as its first argument. For example:
c = RequestContext(request, {
'foo': 'bar',
})
The second difference is that it automatically populates the context with a few variables, according to your TEMPLATE_CONTEXT_PROCESSORS setting.
To access the STATIC_URL setting you need to send a request context because by default the RequestContext instance is automatically populated with some variable, accordingly with the TEMPLATE_CONTEXT_PROCESSORS settings which, by default too, reads this:
(...
"django.core.context_processors.static",
...)
About the django.core.context_processors.static context processor, the docs states:
If TEMPLATE_CONTEXT_PROCESSORS contains this processor, every
RequestContext will contain a variable STATIC_URL, providing the value
of the STATIC_URL setting.
If instead, you don't specify the context_instance=RequestContext(request) part. Consider this signature:
render_to_response(template_name[, dictionary][, context_instance][, mimetype])
In this case a basic Context instance is used and (for this reason) only the given dictionary items get injected into the template. This dictionary could or couldn't contain the value of settings.STATIC_URL.
Note: as pointed out in another answer, since Django 1.3 you can directly use the render shortcut instead of render_to_response() with a context_instance argument.
References to official documentation:
render_to_response
Subclassing Context: RequestContext
django.core.context_processors.static
render shortcut
Since you're on 1.4, use the newer render() shortcut. Then you can do:
def myView(request):
return render(request, 'myTemplate.html', {'user': request.user,})
I am using a context processor to pass several variables to all my templates. However, I would also like use these variables in the actual views that render the respective templates. Should I add them to the session object of the request object or to the request object itself (if at all possible)?
Use RequestContext:
def my_view(request):
c = RequestContext(request)
# c['key'] gets the value for 'key' from your context processor.
return render_to_response('template.html', {}, context_instance = c)
Can't you just get a reference to the context processor and call it in your views? From what I read in the docs, there's nothing special about a context processor:
A context processor has a very simple interface: It's just a Python function that takes one argument, an HttpRequest object, and returns a dictionary that gets added to the template context. Each context processor must return a dictionary.
Custom context processors can live anywhere in your code base. All Django cares about is that your custom context processors are pointed-to by your TEMPLATE_CONTEXT_PROCESSORS setting.
You could have each view access them in the beginning, passing it the request parameter, or maybe create a decorator that would "inject" it in your views for you (whatever's easier in your case).