providing current user to all templates in django project - django

I wonder if there is a way to provide all templates in django application with the current user variable so that I manage login and logout functionality in all pages.
It is a very common practice so there must be an obvious solution I have missed.
I know about the RequestContext Class but that means I have to add it to every view in the application which seems impractical.
May be a custom template tag?

There's a template context processor for this: django.core.context_processors.auth. Check out the documentation, you can access the current user and the permissions in the templates.

You can indeed use a custom tag to achieve that.
Note that by default the custom tag has no access to the request object and therefore to the user data. In order to gain access to the request you can define the custom tag with the takes_context attribute and grab the request from the context:
Something like:
#register.inclusion_tag('userdata.html', takes_context = True)
def userdata(context):
request = context['request']
user = request.user
return {'user':user}

You can just use {{ request.user }} to display the name of the current user, or maybe for example {{ request.user.is_authenticated }} to find out if it's an AnonymousUser or not.

Related

Two separate template profile pages for user his/herself and other users?

Since profile pages should be editable for the user himself/herself,
should I determine the profile owner in view and have a different template just for other users viewing the same page
or
should I use template tags determining whether the current user is the profile owner?
I'm a newb to web app development and Django. Sorry if the question is too broad. Thanks.
You can use a single template and check if user is authenticated in your template and display the necessary code for logged-in users.
To check if user is authenticated in a template, use user.is_authenticated. But, remember that the auth context processor has to be enabled in the settings for the current user to be present in the template context.
You can pass a user_id kwarg in the url to access that user's profile page. You can define your urls something like:
url(r'^user/profile/(?P<user_id>\w+)/$', ProfilePage.as_view(), name='profile_page'),
Then in your views, you can pass the requested_profile_id in the context.
Class ProfilePage(..):
def get_context_data(self):
context = super(ProfilePage, self).get_context_data()
# pass user id for which profile page was requested
context['requested_profile_id'] = self.kwargs.get('user_id')
return context
Then in your templates, check if current user's id is same as the requested_profile_id. If it is same, then you can display the portion to edit profile. You can do something like:
my_template.html
...
<!-- your normal code here -->
..
{% if user.is_authenticated and user.id==requested_profile_id %}
...
<!-- your code for current user profile edit page here -->
..
{% endif %}
You show the himself/herself users profile data based on their userid,so single profile template is enough.
Example:
def profile(request,userid)
.......
return render_to_response('profile.html',{..context..})

django context_processor not understood in templates

i cant quite find it so i hope someone can help me out.
I found the option of using the
TEMPLATE_CONTEXT_PROCESSORS = ("django.contrib.auth.context_processors.auth" )
In django (1.5). But now its not clear for me how i should use it. Should i still put the request in my views, or can i with this enabled use the user_object in my template without sending an extra variably with the Requestcontect
For example:
My view at the moment:
def user_characters(request, user_id):
characters = Character.objects.filter(user=user_id)
user = User.objects.get(id=user_id)
return render_to_response('characters.html',
{'characters': characters, "user": user},
context_instance=RequestContext(request))
My template:
{% extends "base.html" %}
{% block mainframe %}
{% if characters|length < 3 %}
<p>New Character(WN)</p>
{% endif %}
And then the rest of my view.
I notice in almost every view i make i want the user_object send with it.
Can someone please give me an example of how this works?
With kind regards
Hans
django.contrib.auth.context_processors.auth context processor is enabled by default, you don't have to add anything. When you use RequestContext(), a context variable user is available in all templates that you can use. To get id {{userd.id}}.
To check user is authenticated or not, do
{% if user.is_authenticated %}
{# handle authenticated user #}
{%else%}
{# handle anonymous non-authenticated users #}
{%endif%}
You should not expose the user id in the url, you wont need it anyway, if you use django sessions- and the authentication framework. You can always check the logged in user via request.user in your serverside view. With the context processor your should be able to access the user with user.desiredattribute, but you should not need it for the url you try to create.
The docs on this seem pretty clear to me:
https://docs.djangoproject.com/en/dev/ref/templates/api/#django.template.RequestContext
If you want context processors to function, you must ensure that you're using a RequestContext instance. You can do that by explicitly creating it in your views, as you show, or (more conveniently, in my opinion) by using the render shortcut rather than render_to_response as documented here:
https://docs.djangoproject.com/en/dev/topics/http/shortcuts/#render
With the django.contrib.auth.context_processors.auth context processor in place, the user will always be available in the context variable user. At least, assuming your template is being rendered with a RequestContext instance.
You absolutely should not trust a variable obtained from the URL to determine the user if you have any kind of controlled information. With the system you have shown, anyone can view anyone's data simply by editing the URL. That might be OK for a totally insecure application, but it's much more normal to look at request.user.

Retrieving ID from URL

Django question here. So in my base.html, I have a header. The header has links that go to user specific pages. That is, URL's like: /1234/home, /1234/about, etc. where 1234 is the id of a user. My question is, if I want to create a url pointing to a django view method called home with signature home (request, user=0) where user is a different user from the logged in user, how would I do this in the template? To clarify, I am using Django's {% url ... %} template tag and I can't just do {% url [view_name] request.user.id %} because I want the user id from the url, not the id of the logged in user. Additionally, I would prefer avoiding passing a template variable to get the id of the user in the url because then I would have to do that on every page.
Get the id you want as a kwarg to your view, and pass it as a variable to your template through the context to use in the {url ...}.
If you want to persist a variable across all your templates, look at context processors. They are added to each RequestContext so they are accessible to all templates assuming you use the render shortcut or pass the RequestContext to your template.render.
https://docs.djangoproject.com/en/dev/ref/templates/api/#subclassing-context-requestcontext
https://github.com/django/django/blob/stable/1.5.x/django/core/context_processors.py
There are some default ones that django uses. It's fairly simple to add your own.
I imagine your context processor will look something like
context_processors.py
def id_from_url(request):
# Find url id component in request.path
return { 'url_id' : url_id }
Then just add to your settings file appname.context_processors.id_from_url

Django: How to include modelform?

{% include 'django.contrib.auth.views.login' %}
I don't want to write everything by hand.. I hate this really, django full of automatic stuff.
Goal is to include registration/login.html into base.html, so that I could have this form in every page
If I include only template itself (registration/login.html), problem appears that "form.login", I mean "form" var is not defined because this one comes from VIEW which called when you going to login url. So how can I call that view MANUALLY with include or at least to grab django.contrib.auth.views.login variables by my self in my own view and pass then to base.html?
P.s. It's not just about login form, I think there will be more situations like this
I have found better solution in #django irc.
They called inclusion tags
I'll give you my code, because I got lot's of problem learning new stuff in django =)
file: templatetags/form_login.py
from django import template
register = template.Library()
from django.contrib.auth.forms import AuthenticationForm
#register.inclusion_tag('registration/login.html')
def form_login():
return { 'form': AuthenticationForm() }
Now you can have your form anywhere, this will prerender template and THAT'S IT! no stupid context processors which requires to modify whole project settings.py, which is really sux if you writing stand alone little application..
If you need login-form on every page
Create a context processor:
def login_form_processor(request):
return {
'login_form': LoginForm(request.POST or None)
}
Add it to settings.CONTEXT_PROCESSORS.
Include the template for login form:
{% with login_form as form %}
{% include "registration/login.html" %}
{% endwith %}
You can also make you form lazy-loading, so form will not be created until it is used for the first time.
from django.utils improt functional
def login_form_processor(request):
create_login_form = lambda: LoginForm(request.POST or None)
return {
'login_form': functional.lazy(create_login_form, LoginForm)
}
But I guess you won't want the lazy-loading feature, because login-form is cheap to initialize.
Reusing views
Concerning the "grabbing variables" part from your question: you cannot grab variable from view. Django view is method which returns response object. You can not get variables from response. However some of views accept extra_context and other attributes. Those attributes allow you to configure those views in urls, or to wrap them with your own view, for example:
def my_login_view(request):
some_extra_data = get_some_data()
extra_context = {
'some_extra_var': some_extra_data
}
return login_view(request, extra_context=extra_context, template="my_template.html")
This is not exactly grabbing the variables from views, more like augmentation of existing views.
If you expect to have more situations like this, do less data-porcessing in views. Call some methods which checks for permissions. Collect some data from context-processors. Return rendered response. Now you can reuse the data in other views.
You can specify the action on the form html to point to the URL that accesses the corresponding view.
If you want a form, say called as login_form always populated in all templates, then put it in the context_processors.
Browsing the code for django.contrib.auth.views, you will see that the variables form, site and *site_name* are passed to the template.
Either you (1) provide your custom registration form or (2) you can just import django.contrib.auth.forms.AuthenticationForm in your view if you want to use it.

Django: How to write current users name from every view (django)

I am writing small social application. One of the features is to write user name in the header of the site. So for example if I am logged in and my name is Oleg (username), then I should see:
Hello, Oleg | Click to edit profile
Otherwise I should see something like:
Hello Please sign-up or join
What I want is to show this on every page of my site. The obvious solution is to pass request.user object into every view of my site. But here http://www.willmer.com/kb/category/django/
I read that I can simply access request object from any template, just by enabling:
TEMPLATE_CONTEXT_PROCESSORS = (
'django.core.context_processors.request',
)
Not sure why but it actually didn't work :(
Maybe someone can help me and suggest a solution?
Thanks a lot,
Oleg
Also note that you should use django.core.context_processors.auth instead of django.core.context_processors.request if you don't need the whole request context. Then you can simply type:
Hello {{ user.get_full_name }}
in your template.
Don't forget to pass context_instance=RequestContext(request) when you call render_to_response (or use direct_to_template).
There are probably two issues here.
Firstly, if you redefine TEMPLATE_CONTEXT_PROCESSORS as you have done you will override the default, which is probably not a good idea. By default, the setting already includes the auth processor, which gives you a user variable anyway. If you definitely need the request as well you should do this (notice the +=):
TEMPLATE_CONTEXT_PROCESSORS += (
'django.core.context_processors.request',
)
Secondly, as described in the documentation here when using context processors you need to ensure that you are using a RequestContext in your template. If you're using render_to_response you should do it like this:
return render_to_response('my_template.html',
my_data_dictionary,
context_instance=RequestContext(request))
Use
from django.template import RequestContext
instead of
from django.template import Context
So now just call RequestContext(request, context)
More here.
Once you have set up the context process, the request is passed to the template as a variable named request. To access the user object within the variable you need to drill into it:
{{ request.user }}
Here is a list of attributes stored in the Django Request object. More specifically, here is the user attribute.
{% if user.is_authenticated %}
<p>Welcome, {{ user.username }}. Thanks for logging in.</p>
{% else %}
<p>Welcome, new user. Please log in.</p>
{% endif %}
Would be enough if you have TEMPLATE_CONTEXT_PROCESSORS already set.
I think just by adding locals() can solve the problem.
return render_to_response('my_template.html',
my_data_dictionary,locals())