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.
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()?
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 }}
I am working on a web based application in Django. My application is full of widget(not a Django-widgets) which is used for load the different types data using Ajax. For example a 'student' name widgets are loading list of users and a 'teacher' name widget are loading the list of all teacher in a school. To doing this i am getting some following doubts in mind:
I am using templatetag (take a look on the code http://codepad.org/2Ug9Ct3n). In this code when i am doing if request and request.is_ajax():it showing me an error None object has no attribute ajax. The problem is this that i am not able to include request properly. I have already make changes into my setting.py i.e.
TEMPLATE_CONTEXT_PROCESSORS = (
'django.contrib.auth.context_processors.auth',
'django.core.context_processors.static',
'django.core.context_processors.request',
'django.core.context_processors.media',
)
If that thing has no solution then would it be possible for me to write the whole template tag part in views.py? and how?
Instead of that if there are any possibility please post them as a answer!
Any help will be appreciable
Make sure your view (which you haven't posted) is rendering the template with a RequestContext. This happens automatically for you if you're using class based views or the render shortcut.
However, if your're using render_to_response, you need to do the following:
from django.template import RequestContext
from django.shortcuts import render_to_response
def some_view(request):
# ...
return render_to_response('my_template.html',
my_data_dictionary,
context_instance=RequestContext(request))
I would like to write a context processor which will look the existing context, and if there is a form present, check that the user has permission to edit that object. If not, I will overwrite that context variable.
How do I read the existing context from inside a context processor?
Edit:
The reason for using this type of context processor is to avoid having the check permissions with if statements in each view. Some users will have read/write access, others will have read-only and others will have no access, at the object level. I would like to manipulate the form accordingly after the view has been processed.
Why not just wrap the view with a user_passes_test decorator? You can run any checks you like there -- no hacks required.
You should use django-authority, or any authority package. Although, I cannot guarantee that they don't rely on hacks themselves, but at least you wouldn't be alone using the hacks. That said, here is a working solution to your issue:
Monkey patch django.template.base.RequestContext, to set request.context = self.
Create a template context processor, which can use request.context
Add the context processor to settings, and you're good to go
Here is an example, which you can just paste in settings.py, it works:
def print_context(request):
print request.context.get('form', 'No form in this context')
return {}
from django.template.base import RequestContext
orig_init = RequestContext.__init__
def new_init(self, request, **kwargs):
request.context = self
orig_init(self, request, **kwargs)
RequestContext.__init__ = new_init
TEMPLATE_CONTEXT_PROCESSORS = (
'django.core.context_processors.auth',
'django.core.context_processors.debug',
'django.core.context_processors.i18n',
'django.core.context_processors.media',
'django.core.context_processors.request',
'settings.print_context',
)
Note that you are working against Django's design, I posted this answer assuming you know what you're doing - you know both Python and Django very well.