Django authentication logic - django

Where is the appropriate place to distinguish between logged in and not logged in users?
ie. Should there be separate templates for logged in and not logged in users? or one template with if/else statements?

Generally, only small bits of the page will be different for logged in users (though this depends completely on the type of site or system you're building). So the most common situation is to do it as a conditional in the template, e.g.:
{% if user.is_authenticated %}
Show this
{% else %}
Show that
{% endif %}
If you wanted to distinguish in the view logic, e.g. sending different data to the template, it would be something like:
if request.user.is_authenticated:
foo="bar"
else:
foo="baz"

Related

How do i check user authentication on application level Django

How do check the user is authenticated or not when some one try to access a page through url.
ex: http://127.0.0.1/test
when some one types the url i want to check in the page that url redirects, that user is authenticated or not.?
If you're doing it inside view, you can check request.user.is_authenticated(). In some methods of Class-based views, this is not provided as parameter, so you can access it using self.request.
If you're trying to do it inside template:
{% if request.user.is_authenticated %}
You're authenticated!
{% else %}
You're not authenticated :(
{% endif %}
but request must be passed into context, by context processor or by hand, inside your view function.

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.

Include template displaying a form

What I want to do is include a form from a separate template at the bottom of a given page, lets say; "example.com/listdataandform/".
The form-template "form.html" displays the form as it should when the view is included in the URLConf. So I can view with "example.com/form/"
What I have so far goes something like this:
{% extends "base/base.html" %}
{% block title %} page title {% endblock %}
{% block content %}
<h2>some "scene" data</h2>
<ul>
{% for scene in scenes %}
<li>{{ scene.scene }} - {{ scene.date }}</li>
{% endfor %}
</ul>
{% include "tasks/form.html"%}
{% endblock %}
The code inside "block content" works as it should, since it is defined with it's corresponding view for the url "example.com/listdataandform/".
{% include "tasks/form.html"%}: This only displays the submit button from form.html, as expected. I realize by only doing this: {% include "tasks/form.html"%}, the corresponding view method is never executed to provide the "form"-template with data.
Is there any way to this without having to define the view to a specific pattern in urls.py, so that the form can be used without going to the that specified URL..?
So I guess the more general question is; how to include templates and provide them with data generated from a view?
Thanks.
For occasions like this, where I have something that needs to be included on every (or almost every) page, I use a custom context processor, which I then add to the TEMPLATE_CONTEXT_PROCESSORS in settings.py. You can add your form to the context by using this method.
Example:
common.py (this goes in the same folder as settings.py)
from myapp.forms import MyForm
def context(request):
c = {}
c['myform'] = MyForm()
return c
You can also do any processing required for the form here.
Then add it in your settings.py file:
settings.py
.
.
TEMPLATE_CONTEXT_PROCESSORS = (
'''
All the processors that are already there
'''
"myproject.common.context",
)
.
.
I realize by only doing this: {% include "tasks/form.html"%}, the corresponding view method is never executed to provide the "form"-template with data.
Indeed. You included a template, and it really means "included" - ie: "execute in the current context". The template knows nothing about your views, not even what a "view" is.
How does this help me executing the view for the included template to provide it with form data?
It doesn't. A Django "view" is not "a fraction of a template", it's really a request handler, iow a piece of code that takes an HTTP request and returns an HTTP response.
Your have to provide the form to the context one way or another. The possible places are:
in the view
in a context processor (if using a RequestContext)
in a middleware if using a TemplateResponse AND the TemplateResponse has not been rendered yet
in a custom template tag
In all cases this will just insert the form in your template's context - you'll still have to take care of the form processing when it's posted. There are different ways to address this problem but from what I guess of your use case (adding the same form and processing to a couple differents views of your own app), using a custom TemplateResponse subclass taking care of the form's initialisation and processing might just be the ticket.

Django, display count of unread messages in base template

I am working on a project in which I have implemented messaging system like facebook where users can send messages to each other. The number of unread messages of a particular thread is also displayed on the messages page.
Now what I want is to display the count of unread messages in the navigation bar (which is there in base.html) each time user logs in. How to do this whenever a user logs in?
Please suggest, and I don't want to use any other app for this purpose. Thanks
You can write a simple tag which can do this for you.
def unread_messages(user):
return user.messages_set.filter(read=False).count()
#replace the messages_set with the appropriate related_name, and also the filter field. (I am assuming it to be "read")
register.simple_tag(unread_messages)
and in the base template:
{% load <yourtemplatetagname> %}
{% if request.user.is_authenticated %}
{{ request.user|unread_messages }}
{% endif %}

Django - Showing different templates to admins

In Django what's the best way to implement templates with extra functionality for users with 'admin' permissions.
I'm not sure if I should create a set of completely different views specific for admins or integrate it into my existing views and templates like 'if user is an admin' everywhere.
Is there a standard way to do this in Django?
This will show the stuff only if you are active and staff not admin:
{% if request.user.is_active and request.user.is_staff %}
{% include "foo/bar.html" %}
{% endif %}
If you wanna show only and ONLY for admin you have to do that:
{% if request.user.is_superuser %}
ADD your admin stuff there.
{% endif %}
Differences about these fields here.
If you have the the user available in template context you can do:
{% if user.is_active and user.is_staff %}
Only the admin will see this code. For example include some admin template here:
{% include "foo/bar.html" %}
{% endif %}
User will be available in your template f you use RequestContext and your TEMPLATE_CONTEXT_PROCESSORS setting contains django.contrib.auth.context_processors.auth, which is default. See authentication data in templates as reference.
I'm an advocate of keeping as much logic out of the view layer (speaking generally about the MVC Design Pattern). So why not use decorators to direct your user to different views based upon their privilege? In your urls.py, define a pattern for admins:
url(r'^admin/$', 'user.views.admin_index'),
#do so for your other admin views, maybe more elegantly than this quick example
Then define a decorator to kick the user out if they're not an admin
def redirect_if_not_admin(fn):
def wrapper(request):
if request.user.is_staff():
return fn(request)
#or user.is_superuser(), etc
else:
return HttpResponseRedirect('/Permission_Denied/')
return wrapper
And in your admin views
#redirect_if_not_admin
def index(request):
##do your thing
It's more code than the other two answers, which are not wrong. It's just a personal preference to keep clutter down in the views.