Django custom login page condition not working - django

I have 2 login page - login_admin and login_user for admin and normal user respectively.
When user enter username and password in login_admin and login_user page, it will check whether user is_staff is True or False.
If user is_staff = True, then allow the user login admin page.
My problem is: The user can't login to admin page although is_staff = True. The user is able to login to normal user page although is_staff = True. I don't know where is the problem.
Here is my code in views.py:
def login_admin(request):
context = {}
if request.method == 'POST':
username = request.POST['username']
password = request.POST['password']
if username and password:
user = authenticate(username=username, password=password)
if user:
if request.user.is_staff:
login(request, user)
return redirect('/home/')
else:
context['error'] = "You are authenticated but are not authorized to access this page. Would you like to login to a different account?"
return render(request, 'registration/login.html',context)
else:
context['error'] = "Invalid username or password!"
return render(request, 'registration/login.html',context)
return render(request, 'registration/login.html')
def login_user(request):
context = {}
if request.method == 'POST':
username = request.POST['username']
password = request.POST['password']
if username and password:
user = authenticate(username=username, password=password)
if user:
if not request.user.is_staff:
login(request, user)
return redirect('/cust/home/')
else:
context['error'] = "Invalid username or password!"
return render(request, 'registration/custlogin.html',context)
else:
context['error'] = "Invalid username or password!"
return render(request, 'registration/custlogin.html',context)
return render(request, 'registration/custlogin.html')
login.html
{% extends 'base.html' %}
{% block title %}Login{% endblock %}
{% block content %}
<h2>Admin Login Screen</h2>
Customer Login Page
<form method="post">
{% csrf_token %}
<table cellpadding="10">
<tr>
<td><label for="usename">Username: </label></td>
<td><input type="text" name="username" id="username" required></td>
</tr>
<tr>
<td><label for="password">Password: </label></td>
<td><input type="password" name="password" id="password" required></td>
</tr>
<p style="color:red; font-weight: bold">{{ error }}</p>
</table>
<button type="submit" class="btn btn-primary">Login</button>
</form>
{% endblock %}
url.py
url(r'accounts/login/', customers.views.login_admin,name='login_admin'),
url(r'accounts/custlogin/', customers.views.login_user,name='login_user'),
url(r'accounts/logout/', customers.views.logout_user,name='logout_user'),
UPDATED:
I'm not able to sign in to admin page when is_staff = True / False which will return error You are authenticated but are not authorized to access this page. Would you like to login to a different account? which is written in my code, but able to sign in to user page when is_staff=True / False.
If i remove if user.is_staff, it works for admin and normal user.
urls.py
url(r'^accounts/login/$', customers.views.login_admin,name='login_admin'),
url(r'^accounts/custlogin/$', customers.views.login_user,name='login_user'),
url(r'^accounts/logout/$', customers.views.logout_user,name='logout_user'),
UPDATED V2:
I've tried the code that written by #Rarblack but still get error : 'QuerySet' object has no attribute 'is_staff'.
So I've modified the code and it works.
from django.contrib.auth.models import User
if request.method == 'POST':
username = request.POST['username']
password = request.POST['password']
if username and password:
user = authenticate(username=username, password=password)
if user:
user_instance = User.objects.filter(Q(username_exact=username) & Q(is_staff=True))
if user_instance:
login(request, user)
return redirect('/home/')
else:
....

As seen from your code you are getting password and username from the login form and your implementation of it is not correct. You should have used django form or ModelForm and get the input from cleaned_data dict. It should have been something like this:
if request.method == 'POST':
form = ExampleForm(request.POST)
if form.is_valid():
username = form.cleaned_data['username']
password = form.cleaned_data'password']
if username and password:
user = authenticate(username=username, password=password)
......
When we come to your issue, the problem is in this part:
if not request.user.is_staff:
login(request, user)
return redirect('/cust/home/')
what you are basically is doing letting non-staff users in. Change it to:
if request.user.is_staff:
login(request, user)
return redirect('/cust/home/')
EIDT: You are missing request part in the authenticate() method also try this:
user = authenticate(request, username=username, password=password)
if user:
if not user.is_staff:
The problem is that you cannot check any user's staff status because at that time there is no any user logged in to check. So request.user will not return a user. But you can try this:
from django.contrib.models import User
from django.shortcuts import get_object_or_404
if request.method == 'POST':
username = request.POST['username']
password = request.POST['password']
if username and password:
user = authenticate(username=username, password=password)
if user:
user_instance = User.objects.filter(username_exact=username)
if user_instance.is_staff:
login(request, user)
return redirect('/home/')
else:
....

You use if not request.user.is_staff: in both views. For login_admin, if you only want staff to be able to log in, you should change it to:
if request.user.is_staff:

Related

login don't work in django user not login

login dont work i don't where the problem please help.
https://youtu.be/tUqUdu0Sjyc ----- Dennis Ivy -- video learn in youtube
views
from django.contrib.auth import authenticate, login, logout
def login(request):
if request.method == 'post':
username = request.POST.get('username')
password = request.POST.get('password')
user = authenticate(request, username=username, password=password)
if user is not None:
login(request, user)
return redirect('/')
return render(request, 'login.html')
html
<form method="post">
{% csrf_token %}
<input type="username" name="username">
<input type="password" name="password">
<input type="submit" name="submit">
</form>
url
path('login/', views.login, name="login")
There are two problems here:
the request.method is always in uppercase; and
you have a name clash between the view function, and the function of auth.
You thus check this with:
from django.contrib.auth import authenticate
from django.contrib.auth import login as login_auth
from django.contrib.auth import logout
def login(request):
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
user = authenticate(request, username=username, password=password)
if user is not None:
login_auth(request, user)
return redirect('/')
return render(request, 'login.html')

How do i properly show a flash message in django

I have this view function that needs to send a flash message to a user when they sign up. Now that is running well but the problem is that I set an error message to show when the username or password is incorrect and its always showing there by default. Here is my code
views.py
def signup(request):
form = CreateUserForm()
if request.method == 'POST':
form = CreateUserForm(request.POST)
if form.is_valid():
form.save()
user = form.cleaned_data.get('username')
messages.success(request, 'An account was created for ' + user)
return redirect('login')
def login_user(request):
username = request.POST.get('username')
password =
request.POST.get('password')
user = authenticate(username=username, password=password)
if user is not None:
login(request, user)
return redirect('home')
else:
messages.info(request, 'Incorrect Username or Password')
And when I go to the login page its just showing me incorrect username or password even though I just got there
How can I make it to show only when the username or password is incorrect
after mesasge.info redirect to again login page
messages.info(request, 'User not exist')
return redirect('login')
in html file
{% for message in messages %}
<div style="width: 350px; margin-left:500px; " class="alert alert-{{ message.tags }} " id="msg" role="alert">
{{ message }}
{% endfor %}

Authenticate users with both username and email

I have extendted the UserCreationForm with email and other fields, so that I could authenticate a user with both its username and email.
forms.py:
class UserCreationForm(UserCreationForm):
class Meta:
model = User
fields = ('first_name', 'last_name', 'username', 'email',)
views.py:
def auth_view(request):
username = request.POST.get('username','')
password = request.POST.get('password','')
user = auth.authenticate(username=username, password=password)
if user is not None:
auth.login(request, user)
return HttpResponseRedirect('/')
elif:
user = auth.authenticate(email=username, password=password)
if user is not None:
auth.login(request, user)
return HttpResponseRedirect('/')
else:
return HttpResponseRedirect('/accounts/invalid_login')
html:
<form action="/accounts/auth/" method="post">
{%csrf_token%}
<label for="name">Email or Username:</label>
<input type="text" name="name" id="name" value="">
<label for="password">Password:</label>
<input type="password" name="password" id="password" value="">
<input type="submit" value="LOGIN">
</form>
In the views I tried giving both the username and email as input from the form as name, and check to see if username and password authenticate. If not then check whether email and password authenticate. But its not working. How do I solve this problem? Please kindly help me. Thank you.
You need to create an authentication backend: here is mine:
class EmailAuthBackend(ModelBackend):
"""
Email Authentication Backend
Allows a user to sign in using an email/password pair, then check
a username/password pair if email failed
"""
def authenticate(self, username=None, password=None):
""" Authenticate a user based on email address as the user name. """
try:
user = User.objects.get(email=username)
if user.check_password(password):
return user
except User.DoesNotExist:
try:
user = User.objects.get(username=username)
if user.check_password(password):
return user
except User.DoesNotExist:
return None
def get_user(self, user_id):
""" Get a User object from the user_id. """
try:
return User.objects.get(pk=user_id)
except User.DoesNotExist:
return None
Then in your settings:
AUTHENTICATION_BACKENDS = ('MyApp.backends.EmailAuthBackend',)
then create a custom view the uses the authenticate function.

django authentication view doesnt work properly

When I try to login through the login page of my django project, there is the message User with this Username already exists. Here I used my own authentication view:
def login_view(request):
if request.method == 'POST':
form = LoginForm(request.POST)
if form.is_valid():
username = request.POST['username']
password = request.POST['password']
user = authenticate(username=username, password=password)
if user is None:
return HttpResponseRedirect('/logger/bad_login/')
if user.is_active:
login(request, user)
return HttpResponseRedirect('/')
else:
return HttpResponseRedirect('/logger/bad_login/')
else:
form = LoginForm()
return render(request, 'logger/login.html', {'form': form})
Later I found django stock auth views and forms. But still want to know why my view doesnt work properly.
urls.py of my logger app, which used also for saving data of users activity
from django.conf.urls import patterns, include, url
from logger import views
urlpatterns = patterns('',
url(r'^$', views.logger_view, name='log'),
url(r'^login/$', views.login_view, name = 'login'),
url(r'^bad_login/$', views.bad_login_view, name = 'bad_login'),
)
And template
{% extends "base.html" %}
{% block title %}Login {% endblock title %}
{% block content %}
<form action="/logger/login/" method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit" />
</form>
{% endblock content %}
LoginForm
class LoginForm(forms.ModelForm):
class Meta:
model = User
fields = ('username', 'password')
You are using a ModelForm and those will only valid if both the form and the model validation pass.
As you are using the User model, your form does not validate at the model level which is why your view fails.
If you change your login form thus, your view will work as intended:
class LoginForm(forms.Form): # A normal form, not a model form
username = forms.CharField()
password = forms.CharField(widget=forms.PasswordInput)
You might also want to fix your view, so your form errors are displayed correctly, and you are utilizing the form correctly as well:
def login_view(request):
form = LoginForm(request.POST or None)
if form.is_valid():
username = form.cleaned_data['username']
password = form.cleaned_data['password']
user = authenticate(username=username, password=password)
if user is None:
return HttpResponseRedirect('/logger/bad_login/')
if user.is_active:
login(request, user)
return HttpResponseRedirect('/')
else:
return HttpResponseRedirect('/logger/bad_login/')
return render(request, 'logger/login.html', {'form': form})

Django-CSRF: CSRF verification failed. Request aborted when click on login button

I am trying to build a simple website where one can add data into MySQL database. I have a POST form with two text input(username, password). I have read all the related answer and tried to solve it but could not succeed.
index.html
<form action="/login/" method="post">{% csrf_token %}<table border="0" cellspacing="15" width="345" align="center">
<tr>
<td width="100" >Username:</td>
<td><input type="text" class="text-box" value="{{ username }}" placeholder="Username"/></td>
</tr>
<tr>
<td class="align-left">Password:</td>
<td><input type="password" class="text-box" value="" placeholder="Password"/></td>
</tr>
<tr>
<td class="align-left"></td>
forget-link"><a href="#" >Forget Your Passowrd?</a></td>
</tr>
views.py
def login(request):
logout(request)
username = password = ''
if request.method :
username = request.POST['username']
password = request.POST['password']
user = authenticate(username=username, password=password)
if user is not None:
if user.is_active:
login(request, user)
return HttpResponseRedirect('/main/')
return render(request, 'index.html',{ 'username': username})
urls.py
urlpatterns = patterns('',
url(r'^login/', 'mysite.views.login', name='login'),
)
I have applied {% csrf_token %} after form tag in index.html.
When I click on Login button, I have the below error:
CSRF verification failed. Request aborted.
The problem is that you're using the tag {% csrf_token %} in your template but you had not generated the token previously in the view so the template doesn't know anything about it.
Following the docs you have two options:
The first solution:
Use RequestContext, which always uses
'django.core.context_processors.csrf' (no matter what your
TEMPLATE_CONTEXT_PROCESSORS setting). If you are using generic views
or contrib apps, you are covered already, since these apps use
RequestContext throughout.
So you have to change the code in your view like this:
def login(request):
logout(request)
username = password = ''
if request.method :
username = request.POST.get('username', '')
password = request.POST.get('password', '')
user = authenticate(username=username, password=password)
if user is not None:
if user.is_active:
login(request, user)
return HttpResponseRedirect('/main/')
template = loader.get_template('index.html')
context = RequestContext(request,{ 'username': username})
return HttpResponse(template.render(context))
The second solution:
Manually import and use the processor to generate the CSRF token and
add it to the template context. e.g.:
And your code should be (as mcniac told you):
def login(request):
logout(request)
username = password = ''
if request.method :
username = request.POST['username']
password = request.POST['password']
user = authenticate(username=username, password=password)
if user is not None:
if user.is_active:
login(request, user)
return HttpResponseRedirect('/main/')
context = { 'username': username}
context.update(csrf(request))
return render(request, 'index.html',)
I think you need to apply the csrf to your context, your view would endout like this
from django.shortcuts import render_to_response
from django.core.context_processors import csrf
def login(request):
logout(request) # not sure what this function is, I guess must be on some part of your code
if request.method == "POST" :
username = request.POST['username'] or ''
password = request.POST['password'] or ''
user = authenticate(username=username, password=password)
if user is not None:
if user.is_active:
login(request, user)
return HttpResponseRedirect('/main/')
context = { 'username': username, }
context.update(csrf(request))
return render_to_response(request, 'index.html', context)