I was wondering how one would handle a website that, once a user logged in, would be able to show a completely different page to each user?
Think of a master login/registration page.
Once a user registers, depending on their permissions, they would be redirected to the appropriate page for their user type (whilst not being able to access those of any other type).
So would this be an individual user/group permissions thing (using Django auth to do so)? Or would this be able to be implemented using models (i.e. have models of each type of user account and just hold instances in the database)?
This is my first week or so with Django (and web dev), so I am not at all familiar with this stuff.
Redirecting users based on permissions
On the After a user logs in, let's say they land on a URL set by settings.LOGIN_REDIRECT_URL that can you can change to e.g./enter/ URL , and you can map that /enter/ URL to be backed by below view called enter_view()
from django.shortcuts import redirect
def enter_view(request):
if request.user.has_perm('app_label.permission_codename'):
return redirect('/page-A')
elif request.user.has_perm('app_label.another_permission'):
return redirect('/page-B')
else:
return redirect('/page-C')
To change your LOGIN_REDIRECT_URL simply put in settings.py
LOGIN_REDIRECT_URL = '/enter/' # or any URL you want
References
https://docs.djangoproject.com/en/1.8/ref/settings/#login-redirect-url
https://docs.djangoproject.com/en/1.8/ref/contrib/auth/#django.contrib.auth.models.User.has_perm
https://docs.djangoproject.com/en/1.8/topics/http/shortcuts/#redirect
Checking permissions in your template
Further more if you need to customize small parts of a template, you can also check user permissions in similar manner using the {{ perms }} object
{% if perms.foo.can_vote %}
<p>You can vote!</p>
{% endif %}
https://docs.djangoproject.com/en/1.8/topics/auth/default/#permissions
Related
i create a model for website/ frontend . i have 3 types of users. only 1 type i want to see the frontend model. how to create a dynamic access control for the django frontends. please give some solutuion or suggest a plugin. Thanks for solution in advance.
You can do this on the template or views side.
Assuming your preferred user type is 'student', you do this:
Template
{% if user.is_authenticated and user.is_student %}
*content*
{% endif %}
Or this:
Views
Assuming you want to restrict the details of a blog post to only students, you need to create a condition right after defining the 'post_detail_view' view function.
def post_detail_view(request):
if not request.user.is_student:
**do something (eg. raise 404 or httpresponse or redirect)**
**code for this view goes here**
Declaring the restriction in the view allows you to do more than just restrict the content. You can raise a 404 error, redirect the unauthorized user and more. The template solution simply lets you restrict the content.
I hope this solves your problem.
I have created a working Django application. I am using django-allauth for implementing social-account authentication.
Now, suppose I am logged-in inside my application using an e-mail id whose user does not have a staff access and, if I open admin login page directly, the admin login page is displayed as follows:
My question is: how can I stop Django from displaying the message "Successfully signed in as ... "? Where is the source of this message present?
The Successfully signed in message is a message from django-allauth. It uses the messages framework.
I suggest that you add the template code to display messages to your base template. That way, the message will be displayed immediately after you have logged in, rather than when you go directly to the admin login (which does include the template code to display messages).
The text you are referring to (You are authenticated as ...) can be found in this template:
python3.6/site-packages/django/contrib/admin/templates/admin/login.html
You can override this template to remove the messsage. For example, look into this question for how to override djangos default templates.
To override this you need to inherit the template by {% extends "admin/login.html" %}
Then you need to override the block with the name.
{% blocktrans trimmed %} You are authenticated as {{ username }}, but are not authorized to access this page. Would you like to login to a different account? {% endblocktrans %}
Now you can customize this particular line and then point your function to load your custom html file instead of the standard admin ones or you can directly edit the login.html in your django package(Not a good idea). To know where it is fetching from you can do the following...
$python
>>>import sys
>>>sys.path = sys.path[1:]
>>>import django
>>>print(django.__path__)
And then go into contrib\admin\templates\admin and edit the login.html manually.
I was wondering how might I show a new user a message such as 'First time here?' in a Django template using conditionals?
e.g.
{% if this_website_has_not_been_accessed_by_user %}
<h3>First time here?</h3>
<h5>Follow these steps...</h5>
{% endif %}
What might be the best way to do this? Thanks
Assuming you only want to show that banner at the top of the page for logged in users (those that have a User instance in the current request), you could create a Model (or, if you have your own user profile model, add a field to it) to save that.
class Access(models.Model):
user = models.ForeignKey(User)
has_been_here_before = models.BooleanField(default=False)
In your view you would have to check that Model to see if the user is registered there and has the flag set.
See this post for detecting first login.
See also this similar post for detecting a visit to each individual page or view.
EDIT: according to your comments you want to show the welcome banner to anonymous users (not logged in) if they visit for the first time.
You could achieve that using djangos session framework. You can use request.session just like a simple dict.
In your home page view (or through a custom middleware so it affects all pages not just the home page) you could check if a user has already dismissed the welcome banner or not.
def my_home_view(request):
...
# as default 'show_welcome_banner' will be True
context['show_welcome_banner'] = request.session.get('show_welcome_banner', True)
...
Then, in your template use:
{% if show_welcome_banner %}
<h3>First time here?</h3>
<h5>Follow these steps...</h5>
{% endif %}
Your banner could have a 'dismiss' button that posts a hidden to a different url (maybe even through ajax). This url would alter the users session info:
def dismiss_welcome_banner(request):
...
if request.method == 'POST':
request.session['show_welcome_banner'] = False
...
Notes:
if a user access the site through incognito mode (the session cockie gets deleted when he closes the browser) he will need to click the dismiss button every time he opens the incognito browser.
You could additionally check that loggen in users do not get to see that banner, depending of how you prefer it.
I have a navigation bar that displays "login" and "register" when the user is not signed in. When the user is signed in, the navigation bar will display the user's name and the number of messages he has in his inbox.
The problem is that the navigation page is present on around 50 pages, so there are around 50 view functions that have to get the user information and send it to the template. If I want to change this later, it will be a pain!
For example, here is an example view:
def index(request):
user = request.user
...
return render_to_response("page.html", {'user': user})
I have to send the info about the user each time to any page with the navigation bar because my navigation bar contains the code:
{% if user %}
...
{% else %}
....
{% endif %}
Is there a cleaner way to do this?
Edit: Also, I have a UserProfile model which I want to send through to the template. Is there a way to do this, too?
The simplest way is to include django.contrib.auth.context_processors.auth to the TEMPLATE_CONTEXT_PROCESSORS configuration in your settings.py. As described in the docs it wil add a user and perms variable in your template context which gives you direct access to the current user.
Not that the default configuration for TEMPLATE_CONTEXT_PROCESSORS is this (in Django 1.3):
("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.contrib.messages.context_processors.messages")
So the context processor should already be active und you should be able to access the user variable in you templates without returning it in the view.
In your views, you can simply use the render shortcut which will take care of creating the RequestContext instance that is needed:
from django.shortcuts import render
def my_view(request):
return render(request, 'template.html' )
You could create a custom template tag, as DrTyrsa suggested, or you could create context processor.
You need a custom template tag for that.
Why you need to send user to every view, HttpRequest contains the user, you can easily access it in template when you are logged in.
and another solution is, save the user in sessions, and access it in any view or template.
I'm building an app using someone else's API allowing the user to browse content from their site. The user can log into my project with their credentials from this other site in order to "favorite" content from their site.
When they log in, I get a user_token for them. To avoid having to create a user file for them, I just store this token as a session variable:
# Set session
request.session.set_expiry(60 * 60)
# Save token in session
request.session['user_token'] = unicode(auth.Message)
I'm also using file caching for the content from the site:
CACHE_BACKEND = 'file:///..../cache/'
And using the #cache_page command before certain views to cache the data:
#cache_page(CACHE_TIME)
def listings_by_cat_page(request, category_id):
# view stuff here
The problem when I'm running into is when a user views the home screen (which is cached), clicks log in, logs in, and then returns to the home screen, the Login/Logout button doesn't know to switch. I'm assuming it's because since it's a cached page, it doesn't see the user_token session variable.
{% if not request.session.user_token %}
Login
{% else %}
Logout
{% endif %}
Ideally, I'd like to cache the content, but have the page recognize the change in the request.session variables.
Any ideas?
Modify the Vary header and django will generate a new cache key.
Update: I think you should go for the cookie method, as the SessionMiddleware already sets the appropriate Vary headers which is why with Auth, the caching works correctly.
Since you only want to set this once, the cookie method is the way to go I think.
Whichever view handles the logging in of the API method should set a cookie that is a secure hash of the user token and the rest should work, if my thinking is correct.
use {% cache %} tag to cache only parts of the page that are user-independent.