In login, the key to the department is stored in secession and is redirected to the desired department of the user
in login_validation
check = models.user.authenticate(password_entered, username_entered)
if check:
print('valid login')
# check the type of user
request.session['department'] = check['department']
request.session.modified = True
and at logout the the department key is deleted
def logout(request):
if request.session.has_key('department'):
del request.session['department']
request.session.modified = True
return render(request, 'login.html', {'login_form': forms.login_form})
and each page inside the website is checked if department key present if not the user is redirected to the login page
def parts_home(request):
try:
department= request.session['department']
if department != 'parts':
raise Exception
except:
return HttpResponseRedirect(reverse('main:login_page'))
this works fine while hard-coding the URL of the department in the address bar but after pressing back button after logout is called the department key is not checked and the department page is loaded instead of login page. what is the solution?
Try decorator login_required
Add this decorator before your view function.
For example,
from django.contrib.auth.decorators import login_required
#login_required(login_url='/login')
def my_view(request):
....
....
Reference:
the-login-required-decorator
Related
I am newbie to django. I am creating simple order system. I want only logged in user to add items in cart. If user is not looged in, redirect user to login page and after logged in again redirect user to previous page.
This is my views.py
#require_POST
#login_required
def cart_add(request, dish_id):
cart = Cart(request)
dish = get_object_or_404(Dish, id=dish_id)
form = CartAddDishForm(request.POST)
if form.is_valid():
cd = form.cleaned_data
cart.add(dish=dish, quantity=cd['quantity'], update_quantity=cd['update'])
return redirect('cart:cart_detail')
You should swap the decorators. Right now the view function is first decorated with #login_required, and then decorated with #require_POST. But that means that if you make a request that is not a POST request, it will return a 405 error, regardless whether the user is logged in.
By swapping the decorators, it will first check if the user is logged in, if that is not the case, it will redirect the user to the login view. If the user is logged in, but the method is not POST, it will return a 405 error.
#login_required
#require_POST
def cart_add(request, dish_id):
# …
Note that redirecting to cart_add however does not make much sense, since it requires a POST request, and this thus means that it will raise a 405 after logging in.
def cart_add(request, dish_id):
if request.user.is_authenticated: #checks user is logined or not
cart = Cart(request)
dish = get_object_or_404(Dish, id=dish_id)
form = CartAddDishForm(request.POST)
if form.is_valid():
cd = form.cleaned_data
cart.add(dish=dish, quantity=cd['quantity'], update_quantity=cd['update'])
return redirect('cart:cart_detail')
else:
return redirect('login_page')
I am trying to have two different redirects...one for normal login and another for redirect after email confirmation
ACCOUNT_EMAIL_CONFIRMATION_AUTHENTICATED_REDIRECT_URL = '/profile'
LOGIN_REDIRECT_URL = '/'
But when I enable login, AUTHENTICATED REDIRECT goes to LOGIN_REDIRECT but when I disable Login it goes to the EMAIL_CONFIRMATION_REDIRECT route.
When I try printing the adapter settings for email_confirmation redirect url below it shows only the LOGIN_REDIRECT
def get_email_confirmation_redirect_url(self, request):
""" The URL to return to after successful e-mail confirmation. """
if request.user.is_authenticated:
if app_settings.EMAIL_CONFIRMATION_AUTHENTICATED_REDIRECT_URL:
return \
app_settings.EMAIL_CONFIRMATION_AUTHENTICATED_REDIRECT_URL
else:
return self.get_login_redirect_url(request)
else:
return app_settings.EMAIL_CONFIRMATION_ANONYMOUS_REDIRECT_URL
I tried overriding this get_email_confirmation_redirect_url in the adapter but still wont work. It is not picking the REDIRECT before I login and reverify.
Since ACCOUNT_EMAIL_CONFIRMATION_AUTHENTICATED_REDIRECT_URL = '/profile' was not working if the user is not logged in, I decided to override DefaultAccountAdapter in Django Allauth. My login was that if the time the user joined the app and the time logged in exceeds a certain threshold, then the redirection would be different. So I created an adapter in my users app as below:
class AccountAdapter(DefaultAccountAdapter):
def get_login_redirect_url(self, request):
expiry = 90 #seconds
assert request.user.is_authenticated
if (request.user.last_login - request.user.date_joined).seconds < expiry:
url = 'profile/'
else:
url = settings.LOGIN_REDIRECT_URL
return resolve_url(url)
I then passed this adapter in my settings.py
I am implementing a functionality where a user is forced to change a password (i.e. if the admin creates an initial password, the user is required to change it on the next login). I am using the Django Contrib Auth package.
For this, I have a extended the user profile by a boolean parameter force_password_change:
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
force_password_change = models.BooleanField(default=True)
In my view, I am extending the standard LoginView:
class MyLoginView(LoginView):
def form_valid(self, form):
# form is valid (= correct password), now check if user requires to set own password
if form.get_user().profile.force_password_change:
return HttpResponseRedirect('password_change')
else:
auth_login(self.request, form.get_user())
return HttpResponseRedirect(self.get_success_url())
The system renders a 404 page not found error after I click the login button: The current path, accounts/login/, didn't match any of these.
I noticed that when I add auth_login(self.request, form.get_user()) just before the HttpResponseRedirect('password_change') it works fine. But this also means that the user is (incorrectly) authenticated.
urls.py:
path('', myapp.MyLoginView.as_view(), name='login'),
path('password_change/', myapp.MyPasswordChangeView.as_view(), name='password_change'),
Why is this the case and why is the 404 error refering to accounts/login/?
You need to use reverse for resolving the url name:
from django.urls import reverse
class MyLoginView(LoginView):
def form_valid(self, form):
# form is valid (= correct password), now check if user requires to set own password
if form.get_user().profile.force_password_change:
return HttpResponseRedirect(reverse('password_change'))
else:
auth_login(self.request, form.get_user())
return HttpResponseRedirect(self.get_success_url())
Use User.set_unusable_password, then assuming your password change view is called 'change-password':
Add this to your login view:
from django.http import HttpResponseRedirect
from django.urls import revese
if not user.has_usable_password():
return HttpResponseRedirect(reverse('change-password')
I have successfully made it so the user must log in to view their profile, however, I only want the user to be able to view their profile and no one else.
Previously, they could visitwww.websitename.com/user/admin
as well as www.websitename.com/user/test and it would bring up the data for the profile each time of the logged in user.
The URL to visit is www.websitename.com/user/usernameofcurrentuser
Profile Page View
def profile_page(request, username):
context = RequestContext(request)
if request.user == username:
if request.user.is_authenticated():
user = User.objects.get(username=username)
taskitems = request.user.taskitem_set.all()
return render_to_response('profile.html', {}, context)
else:
return render_to_response('login.html', {}, context)
else:
return render_to_response('login.html', {}, context)
However, even though the user is logged in, it's redirecting them to the sign in page. I know the user is logged in because it prints their name on the login page, yet it's not redirecting them to the profile associated with the username.
You can try this :
def profile_page(request, username):
if request.user.is_authenticated():
if request.user.username == username:
# removed user since already in request.user and available in template as 'user'
# removed taskitems since directly available in template as 'user.taskitem_set.all'
return render(request, 'profile.html')
else:
return HttpResponseRedirect(reverse('profile_page', args=(request.user.username,)))
else:
return render(request, 'login.html')
Remove the username parameter since each user should only view their own profile. You can also use the login_required decorator to remove the extra conditional:
from django.contrib.auth.decorators import login_required
from django.shortcuts import render
#login_required
def profile_page(request):
return render(request, 'profile.html')
Make sure to set LOGIN_URL in your settings.py so unauthenticated users get redirected to the right spot.
i have my login form in the homepage itself i.e. "/". now from there i want to redirect a user to 0.0.0.0:8000/username where 'username' is not static, it i different for different users.
I'm a beginner to Django. Pls explain in dept. Thanks in advance
what you could do is define a home url and a profile url in your urls.py like this.
#urls.py
url(r'^$', 'app.views.home'),
url(r'^(?P<username>\w+)/$', 'app.views.profile'),
now under views.py define 2 views one to render the home page and second to render the profile page
# views.py
import models
from django.shortcuts import render_to_response
from django.templates import RequestContext
from django.contrib.auth import authenticate, login
def home(request):
"""
this is the landing page for your application.
"""
if request.method == 'POST':
username, password = request.POST['username'], request.POST['password']
user = authenticate(username=username, password=password)
if not user is None:
login(request, user)
# send a successful login message here
else:
# Send an Invalid Username or password message here
if request.user.is_authenticated():
# Redirect to profile page
redirect('/%s/' % request.user.username)
else:
# Show the homepage with login form
return render_to_response('home.html', context_instance=RequestContext(request))
def profile(request, username):
"""
This view renders a user's profile
"""
user = user.objects.get(username=username)
render_to_response('profile.html', { 'user' : user})
Now when the first url / is requested it forwards the request to app.views.home which means the home view ===within===> views.py ===within===> app application.
the home view checks if a user is authenticated or not. if a user is authenticated it calls the url /username otherwise it simply renders a template called home.html in your templates directory.
The profile view accepts 2 arguments, 1. request and 2. username. Now, when the profile view is called with the above mentioned arguments it gets the user instance for the username provided and stores it in a user variable and later passes it to the profile.html template.
also please do read through the very easy Poll Application Tutorial on Django Project to get familiar with the power of django.
:)