Best way to pass current Django view's name into the template? - django

Suppose I have a view handler like this:
#require_GET
def FooView(request):
# do stuff...
return render_to_response(
'foo.html',
{
# some data...
'current_view': 'FooView' # the eyesore
}
)
I need the 'current_view' value for marking the current menu item, breadcrumbs, etc.
Is there an easy / established way to make the current view name available to the template?
Of course I can construct a per-view class and use self.__class_.__name__ or something; I'm interested in an easy and established, Django-idiomatic way, it it exists.
I'm using Django 1.4.

You could use a Context Processor to fill this information and have it automatically in all you templates
from django.core.urlresolvers import resolve
def custom_context_processor(request):
return {'view_name': resolve(request.path)[0]}
you can than add this context processor in your settings to the TEMPLATE_CONTEXT_PROCESSORS tuple. That way you can access it in every templates like in the following snippet :
{{ view_name }}

Related

Django include the same variables in all views

I want to include the same variables in all the views , to avoid repeating , i've been looking at django docs and found the generic display views and i tried it but it doesnt seems to work.
Any idea how to do this ?
Write a template context processor:
def add_foo(request):
return {'var': 'foo'}
Save this to a file, lets say custom_context.py, put it inside the same directory as your views.py.
Then, add it to your TEMPLATE_CONTEXT_PROCESSORS setting - make sure you keep the default ones, otherwise other functions may not work. You need to add the Python path, so add yourapp.custom_context.add_foo,
Now, whenever you return a RequestContext instance (you can do this by using the render shortcut, and all class based views automatically return a RequestContext instance); the variable var will be available in your templates, as {{ var }}.

how to create a reusable function available across apps in django

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):
....

How to get the name of current app within a template?

What's the simplest way to access the name of the current app within template code?
Alternatively, what's the simplest way to define a template variable to hold the name of the current app?
(The goal here is to minimize the number of places I need to edit if I rename an app.)
Since Django 1.5 there is a "resolver_match" attribute on the request object.
https://docs.djangoproject.com/en/dev/ref/request-response/
This contains the matched url configuration including "app_name", "namespace", etc.
https://docs.djangoproject.com/en/2.2/ref/urlresolvers/#django.urls.ResolverMatch
The only caveat is that it is not populated until after the first middleware passthrough, so is not available in process_request functions of middleware. However it is available in middleware process_view, views, and context processors. Also, seems like resolver_match is not populated in error handlers.
Example context processor to make available in all templates:
def resolver_context_processor(request):
return {
'app_name': request.resolver_match.app_name,
'namespace': request.resolver_match.namespace,
'url_name': request.resolver_match.url_name
}
There's a way to obtain an app name for a current request.
First, in your project's urls.py, considering your app is called 'main':
#urls.py
url(r'^', include('main.urls', app_name="main")),
Then, a context processsor:
#main/contexts.py
from django.core.urlresolvers import resolve
def appname(request):
return {'appname': resolve(request.path).app_name}
Don't forget to enable it in your settings:
#settings.py
TEMPLATE_CONTEXT_PROCESSORS = (
"django.core.context_processors.request",
"main.contexts.appname",)
You can use it in your template like any other variable: {{ appname }}.

Django: Define a template context processor in all templates without creating a new view

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

Always send the User information in every Django template

I used a pre-built example templates for Django registration and I noticed that for those pages, Django understands user and I do things like user.is_authenticated and user.username.
I tried looking at the views.py code in both Django registration and the django.contrib.auth.views, but I couldn't figure out how those two always sent the user information to the templates.
I could could always explicitly send the user Context information to every view, but that would be violating the DRY principle.
I tried using this solution, but I get an error saying
Put 'django.contrib.auth.context_processors.auth' in your TEMPLATE_CONTEXT_PROCESSORS setting in order to use the admin application.
And even if I placed the above path inside settings.py like this
TEMPLATE_CONTEXT_PROCESSORS = (
'django.contrib.auth.context_processors.auth',
'doors.processor_file_name.user',
)
my templates still doesn't know about user.
It turns out that every time I was using render_to_response in my views.py...
def order_all( request ) :
orders = Order.objects.all()
return render_to_response( 'doors/order/list.html', { 'orders' : orders } )
the dictionary isn't a RequestContext. Using a RequestContext will automatically include the TEMPLATE_CONTEXT_PROCESSORS, which in my case will include django.contrib.auth.context_processors.auth, which will pass along the user information to the every template.
So in other words, I just need to change the code above to this
def order_all( request ) :
orders = Order.objects.all()
return render_to_response( 'doors/order/list.html', context_instance = RequestContext( request, { 'orders' : orders } ) )
Don't forget to import RequestContext too
from django.template import RequestContext
It also turns out I don't need to explicity include django.contrib.auth.context_processors.auth (or write my custom doors.processor_file_name.user) in the TEMPLATE_CONTEXT_PROCESSORS because django.contrib.auth.context_processors.auth is included by default
I realise this is an old question, but for anyone else who runs into this problem, you could use "render", instead of "render_to_response":
def order_all(request):
orders = Order.objects.all()
return render(request, 'doors/order/list.html', { 'orders': order })
This also negates the need to import RequestContext. According to the django docs, "render" is the same as "render_to_response", but has a context instance argument that forces the use of RequestContext.