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.
Related
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')
my login page:
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'>
<meta http-equiv='X-UA-Compatible' content='IE=edge'>
<title>Page Title</title>
<meta name='viewport' content='width=device-width, initial-scale=1'>
<link rel='stylesheet' type='text/css' media='screen' href='main.css'>
<script src='main.js'></script>
</head>
<body>
<form action="login" media="post">
{% csrf_token %}
<input type="text" name="username" placeholder="username"><be>
<input type="password" name="password" placeholder="password"><be>
<input type="Submit">
</form>
</body>
</html>
views.py :
from django.shortcuts import render, redirect
from django.contrib import messages
from django.contrib.auth.models import User, auth
from django.contrib.auth import authenticate
# Create your views here.
def homepage(request):
return render(request, 'homepage.html')
def login(request):
if request.method== 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
user = authenticate(username=username, password=password)
if user is not None:
auth.login(request, user)
return redirect("/")
else:
messages.success(request,'password not matching')
return redirect('home')
else:
return render(request,'login.html')
def registration(request):
if request.method == 'POST':
first_name = request.POST['first_name']
last_name = request.POST['last_name']
username = request.POST['username']
password = request.POST['password']
confirmpassword = request.POST['confirmpassword']
email = request.POST['email']
if password==confirmpassword:
if User.objects.filter(username=username).exists():
messages.info(request, 'Username Taken')
return redirect('/registration')
elif User.objects.filter(email=email).exists():
messages.info(request, 'Email Taken')
return redirect('/registration')
else:
user = User.objects.create_user(username=username,
password=password, email=email, first_name=first_name, last_name=last_name)
user.save();
print('user successfully created')
return redirect('login')
else:
messages.info(request,'password not matching')
return redirect('/registration')
return redirect('/')
else:
return render(request, 'registration.html')
my urls.py:
from django.urls import path
from . import views
urlpatterns = [
path('',views.homepage, name='homepage'),
path('login',views.login, name='login'),
path('registration',views.registration, name='registration'),
]
every single time this login page is redirecting to same login page, whether I enter wrong credentials or the right one, I think its not even verifying the credentials that whether they are right or wrong. please help me out.
please help me out.
please help me out.
please help me out.
please help me out.
You checked if there is a user with as username 'username' and as password 'password', you do not use the user and password variables, but strings that contain username and password as content. You thus should use variables:
# not 'username' and 'password'
user = authenticate(username=username, password=password)
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:
I try to login users from MyUser model in django 1.5. I use e-mail as login, see model:
class MyUser(AbstractBaseUser):
email = models.EmailField(
verbose_name='email address',
max_length=255,
unique=True,
db_index=True,
)
last_name=models.CharField(max_length=30)
first_name=models.CharField(max_length=30)
second_name=models.CharField(max_length=30, blank=True)
post=models.CharField(max_length=30, blank=True)
objects = MyUserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['last_name','first_name','second_name','post',]
def get_full_name(self):
return self.email
def get_short_name(self):
return self.email
def __unicode__(self):
return self.email
def has_perm(self, perm, obj=None):
return True
def has_module_perms(self, app_label):
return True
#property
def is_staff(self):
return self.is_admin
And I added LoginForm:
class LoginForm(forms.Form):
username = forms.CharField(max_length=100)
password =forms.CharField(widget=forms.PasswordInput(render_value=False),max_length=100)
view:
def login_view(request):
if request.method == 'POST':
username = request.POST['email']
password = request.POST['password']
user = authenticate(username=username, password=password)
if user is not None and user.is_active:
login(request, user)
return HttpResponseRedirect("/home.html")# Redirect to a success page.
return HttpResponseRedirect("/account/invalid/")# Return a 'disabled account' error message
form=LoginForm()
return render(request, 'enter.html', {'login_form': LoginForm})
template:
{% if form.errors %}
<p>Something is wrong</p>
{% endif %}
<form action="" method="post">
{% csrf_token %}
<label for="email">Login:</label>
<input type="text" name="email" value="" id="email"/>
<label for="password">Password:</label>
<input type="password" name="password" value="" id="username">
<input type="submit" value="login" />
<input type="hidden" name="next" value="{{next|escape}}" />
</form>
urls:
(r'^login/$', login_view),
Problem: It works for users from default User model (username, password), but this form "doesn't know" users from MyUser model (email, password), it redirect them to /account/invalid page.
What am I doing wrong?
Thx!
You need to indicate your custom user model in settings:
AUTH_USER_MODEL = 'myapp.MyUser'
Also, you have to provide custom UserManager, from doc:
You should also define a custom manager for your User model. If your
User model defines username and email fields the same as Django’s
default User, you can just install Django’s UserManager; however, if
your User model defines different fields, you will need to define a
custom manager that extends BaseUserManager providing two additional
methods:
I have a simple signup form (in signup.html)
<form action="adduser" method="post">
{% csrf_token %}
Email Address: <input type="email" name="email" required autocomplete="on" placeholder="fr#star.com"/><br/>
Username: <input type="text" name="username" maxlength=25 required placeholder="JoyfulSophia"/><br/>
Password: <input type="password" name="password" maxlength=30 required placeholder="**********" /><br/>
<br/>
<input type="submit" value="Send" /> <input type="reset">
</form>
This redirects to the addUser view:
def adduser(request):
u = User.objects.create_user(request.POST['username'], request.POST['email'], password=request.POST['password'])
u.save()
a = Accounts(user=u)
p = Passwords(user=u)
a.save()
p.save()
return HttpResponseRedirect(reverse('OmniCloud_App.views.profile', args=(u.id,)))
Here is the profile:
#login_required
def profile(request, User_id):
u = get_object_or_404(User, pk=User_id)
a = get_object_or_404(Accounts, pk=User_id)
return render_to_response('profile.html', context_instance=RequestContext(request))
So they wouldn't be signed in, but that's okay because we can send you over to /accounts/login?next=/7/ since they are user 7 (Problems Ahead!)
def login(request):
username = request.POST['username']
password = request.POST['password']
user = auth.authenticate(username=username, password=password)
if user is not None and user.is_active:
auth.login(request, user)
return HttpResponseRedirect("/account/profile/")
else:
return HttpResponseRedirect("/account/invalid/")
The request doesn't contain anything called username, but the one which was submitted to the addUser form does, so how can I shoot that bro over to login? I could have it parse the url (which contains the next=USER_ID) but that wouldn't work for someone that just types in base_url/login, and the user_id won't be part of the url forever. So what's a brother to do?
Post data exists only for one request. If you want to use it later you should save it somewhere else.
You could login the user right after registration, in adduser view, he just entered his username and password, he doesn't have to do it again.
And login view is a little off. This is just a "POST" part of the view. You need to check and see if it's GET request and if it is return template with form containing username and password fields and with target url that points to the same view. Something like this:
def login(request):
if request.method == 'GET':
return render_to_response('login.html',
{ 'form': LoginForm() },
context_instance=RequestContext(request))
elif request.method == 'POST':
form = LoginForm(request.POST)
if form.is_valid():
username = form.cleaned_data['username']
password = form.cleaned_data['password']
user = auth.authenticate(username=username, password=password)
if user is not None and user.is_active:
auth.login(request, user)
return HttpResponseRedirect("/account/profile")
else:
return HttpResponseRedirect("/account/invalid/")
Where login.html is something like this:
{% extends "base_site.html" %}
{% block content %}
<form method="post" target="{% url login_view %}">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Login" />
</form>
{% endblock content %}
Also, you could return user to the same login form if username and password didn't match and add some message!
This is just from the top of my head, didn't try it, but it should work!
There is an extensible user-registration application for Django called django-registration that offers you a lot of functionality for creating and registering users. Setting it up is very simple, you can find a very good doc here