I'm trying to create a custom session-based login in Django using a custom user model and a custom login template.
For some reasons it worked at first but now the authenticate method from django.contrib.auth is not authenticating user. When it did work, the login and signup button were hidden.
users/urls.py
app_name = 'users'
urlpatterns = [
path('login/', login_user, name='login_user'),
path('logout/', logout_user, name='logout_user'),
]
users/views.py
app_name = 'users'
def login_user(request):
django_logout(request)
message = ''
if request.method == 'POST':
email = request.POST['email']
password = request.POST['password']
user = authenticate(request, email=email, password=password)
if user is not None:
django_login(request, user)
return redirect('homepage')
else:
message = "Log in failed!"
messages.error(request, message)
return redirect('users:login_user')
else:
return render(request, 'users/login.html')
#login_required(login_url='users/login/')
def logout_user(request):
django_logout(request)
templates/users/login.html
<form class="bg-white rounded-5 shadow-5-strong p-5" method="post" action="/">
{% csrf_token %}
<!-- Email input -->
<div class="form-outline mb-4">
<label class="form-label" for="form1Example1">Email address</label>
<input type="email" name="email" id="form1Example1" class="form-control" />
</div>
<!-- Password input -->
<div class="form-outline mb-4">
<label class="form-label" for="form1Example2">Password</label>
<input type="password" type="password" id="form1Example2" class="form-control" />
</div>
<!-- Submit button -->
<button type="submit" class="btn btn-primary btn-block">Sign in</button>
</form>
users/models.py
class CustomUserManager(BaseUserManager):
def create_superuser(self, email, password):
if email is None:
raise TypeError('Users should have an Email')
if password is None:
raise TypeError('Password should not be none')
user = self.create_user(email, password)
user.is_superuser = True
user.is_staff = True
if user.is_superuser is not True:
raise ValueError(
'Superuser must be assigned to is_staff=True.')
if user.is_staff is not True:
raise ValueError(
'Superuser must be assigned to is_superuser=True.')
user.save()
return user
def create_user(self, email, password):
if email is None:
raise TypeError('Users should have an Email')
if password is None:
raise TypeError('Users must have a password')
email = self.normalize_email(email)
user = self.model(email=email)
user.set_password(password)
user.save()
return user
AUTH_PROVIDERS = {'facebook': 'facebook', 'google': 'google',
'twitter': 'twitter', 'email': 'email'}
class CustomUser(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(max_length=255, unique=True, db_index=True)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
about = models.TextField(_(
'about'), max_length=500, blank=True)
auth_provider = models.CharField(
max_length=255, blank=False,
null=False, default=AUTH_PROVIDERS.get('email'))
USERNAME_FIELD = 'email'
objects = CustomUserManager()
def __str__(self):
return self.email
My sign in button in homepage.html
<a href="{% url 'users:login_user' %}">
<button type="button" class="btn btn-link px-3 me-2">
Login
</button>
</a>
Could you show me the way to solve this? Thank you!
Change your form like this
<form class="bg-white rounded-5 shadow-5-strong p-5" method="post" action="{% url 'users:login_user' %}">
{% csrf_token %}
<!-- Email input -->
<div class="form-outline mb-4">
<label class="form-label" for="form1Example1">Email address</label>
<input type="email" name="email" id="form1Example1" class="form-control" />
</div>
<!-- Password input -->
<div class="form-outline mb-4">
<label class="form-label" for="form1Example2">Password</label>
<input type="password" name="password" type="password" id="form1Example2" class="form-control" />
</div>
<!-- Submit button -->
<button type="submit" class="btn btn-primary btn-block">Sign in</button>
</form>
MultiValueDictKeyError at /users/login/ 'password'
this is because you're trying to access password value from request like this request.POST['password'] but you've not set name to your input(password) that's why it is giving you an error
Related
I want to create django login form with bootstrap 5. How can i ensure that the form is valid? Can i styling raise validationError with bootstrap in template?
Here is my code:
forms.py
class LoginForm(forms.Form):
username = forms.CharField()
password = forms.CharField()
def clean(self):
username = self.cleaned_data.get("username")
password = self.cleaned_data.get("password")
# Check if user and password is matching and exists
user = authenticate(username=username, password=password)
if not user:
raise forms.ValidationError("This is an invalid user.")
login_page.html
<form method="POST" class="row g-3 needs-validation" novalidate>
{% csrf_token %}
<input type="text" name="username" class="form-control" placeholder="Username" required>
<div class="invalid-feedback">{{ #raise ValidationError here }}</div>
<input type="password" name="password" class="form-control" placeholder="Password" required>
<div class="invalid-feedback">{{ #raise ValidationError here }}</div>
<input class="btn btn-primary" type="submit" value="Login">
Can i do that? Or is there a better solution to create login form validation?
Thankyou.
you can pass validation here like this in your forms.py
forms.py
class LoginForm(forms.Form):
username = forms.CharField()
password = forms.CharField(widget=forms.PasswordInput)
def clean(self, *args, **kwargs):
username = self.cleaned_data.get("username")
password = self.cleaned_data.get("password")
if username and password:
user = authenticate(username=username, password=password)
if not user:
raise forms.ValidationError("This user doesn't exist")
if not user.check_password(password):
raise forms.ValidationError("Incorrect Password")
if not user.is_active:
raise forms.ValidationError("User no longer Active")
return super(LoginForm,self).clean(*args,**kwargs)
I tried creating a new user but it didn't work, I have tried debugging it but don't get a way about this. I have a User Model but want to try and create different user types like students, teachers something like that which would all be in the user user model as well as their various user models.
View.py
def AddCustomerManager(request):
if request.method == "POST":
email = request.POST.get('email')
username = request.POST.get('username')
password = request.POST.get('password')
try:
user = User.objects.create_user(email=email, username=username, password=password, user_type=2)
user.save()
messages.success(request, "Customer Manager Added Successfully")
except:
messages.error(request, "Failed to Add Customer Manager")
return render(request, "pusheat_admin/addcm.html")
models.py
class User(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(_('email address'), unique=True)
is_staff = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
user_type_choice = ((1, "SuperUser"), (2, "CustomerManager"))
user_type = models.CharField(default=1, choices=user_type_choice, max_length=10)
objects = UserManager()
class CustomerManager(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
fullname = models.CharField(max_length=50, blank=False)
email = models.EmailField()
password = models.CharField(max_length=32)
addcm.html
<form role="form" method="POST">
{% csrf_token %}
<div class="card-header"><h4>Add Customer Manager</h4></div>
<div class="card-body">
<div class="form-group">
<label>Email address</label>
<input type="email" class="form-control" name="email" placeholder="Enter email">
</div>
<div class="form-group">
<label>Username</label>
<input type="text" class="form-control" name="username" placeholder="Username">
</div>
<div class="form-group">
<label>Password</label>
<input type="password" class="form-control" name="password" placeholder="Password">
</div>
</div>
<div class="card-footer">
<button type="submit" class="btn btn-primary">Add Customer Manager</button>
</div>
</form>
Change this line in models.py:
user_type = models.CharField(default=1, choices=user_type_choice, max_length=10)
to:
user_type = models.PositiveSmallIntegerField(default=1, choices=user_type_choice, max_length=10)
ImproperlyConfigured at /accounts/register
Could not create directory for saving email messages: /home/user/Desktop/emails ([Errno 13] Permission denied: '/home/user')
It points to this line "user.email_user(subject, message, html_message=message)" in views.register in account.
auth.html
<form id='registration-form' method='post' action={% url 'accounts:register' %}>
{% csrf_token %}
<div class="form-group">
<input type="text" class="form-control input-upper" id="fullname" placeholder="John Doe" name="fullname" required><br>
<input type="text" class="form-control input-upper" id="username" placeholder="Username" name="username"><br>
<input type="email" class="form-control input-upper" id="email" placeholder="Email" name="email" required><br>
<input type="text" class="form-control input-upper" id="organization" placeholder="Organization" name="organization" required><br>
<input type="password" class="form-control input-upper" id="password" placeholder="Password" name="password1" required><br>
<input type="password" class="form-control input-upper" id="password" placeholder="Confirm Password" name="password2" required><br>
<small>By registering you agree to our terms and conditions</small>
<button type="submit" value='register' id='reg-submit-btn' class="btn btn-primary btn-block btn-signup-form">SIGN UP</button>
<button type="button" class="btn btn-primary btn-block btn-sign-linkedin" href="{% url 'social:begin' 'linkedin-oauth2' %}?next={{ next }}">Sign up with LinkedIn</button>
<p class="text-already">Already have an account? <a href="" >LOGIN</a></p>
</div>
</form>
MOdel Userprofile.py
class UserProfile(models.Model):
""" Profile for the User Model """
user = models.OneToOneField(
User, on_delete=models.CASCADE,
related_name='profile',
verbose_name='other Details',
)
phone = models.CharField(max_length=11, default='', blank=True, null=True)
organization = models.CharField(default='', max_length=300, blank=True)
referral = models.OneToOneField(
Referral, on_delete=models.CASCADE,
related_name='profile', verbose_name='profile Details',
null=True)
email_confirmed = models.BooleanField(default=False)
def __str__(self):
return self.user.username + '\'s profile'
def activate(self):
"""" Activates account after email is confirmed """
self.email_confirmed = True
self.user.is_active = True
self.save()
self.user.save()
Views.py
#transaction.atomic
def register(request):
"""Process registration of new users"""
if request.user.is_authenticated:
return JsonResponse({'status': 'loggedin'})
status = dict()
status['status'] = 'failure'
if request.method == 'POST':
form = RegistrationForm(request.POST)
if form.is_valid():
# Save Profile details
user = form.save()
current_site = get_current_site(request)
subject = 'DHIS2 Account Activation'
message = render_to_string(
'registration/account_activation_email.html',
{
'user': user,
'domain': current_site.domain,
'uid': urlsafe_base64_encode(
force_bytes(
user.pk)).decode(),
'token': account_activation_token.make_token(user),
},
request=request)
user.email_user(subject, message, html_message=message)
Referral.record_response(request, "REGISTERED")
#return JsonResponse({'status': 'success'})
return redirect('accounts:account_activation_sent')
status = form.errors
status['status'] = 'failure'
return JsonResponse(status)
I get a json response of status:Failure, and password1: "This field is required." and password2:"This field is required.
What could I be doing wrong? Probably the template doesn't save or something. How do i make a custom django form that makes use of the html template.
You don't have fields with names password1 and password2 in your template; you just have two fields named password. You need to give them the correct name attributes.
I'm working on creating a custom authentication login. Everything seems to be working, except the display of an error message when the email and password are incorrect.
I know it has something to do with my rendering of the login.html page upon failure of logging in and not supplying the form with the fact that there was an attempted login failure, but I'm not sure how to go about putting that in my code.
views.py
from django.shortcuts import render_to_response
from django.contrib.auth.decorators import login_required
from django.shortcuts import render_to_response
from django.template import RequestContext
from django.contrib.auth import authenticate, login, logout
from django.http import HttpResponseRedirect
def login_user(request):
logout(request) #logs out user upon reaching the /login/ page
email = password = ''
if request.POST:
email = request.POST['email']
password = request.POST['password']
user = authenticate(email=email, password=password)
if user is not None:
if user.is_active:
login(request, user)
return HttpResponseRedirect('/successful_login/')
else:
state = "Your account is not active, please contact the administrator."
else:
state = "Your email and/or password were incorrect."
state = "Please log in below..."
context = RequestContext(request, {
'state': state,
'email': email,
})
return render_to_response('customauth/login.html', {}, context)
#login_required(login_url='/login/')
def successful_login(request):
return render_to_response('customauth/successful_login.html');
models.py
from django.db import models
from django.contrib.auth.models import (
BaseUserManager, AbstractBaseUser
)
class MyUserManager(BaseUserManager):
def create_user(self, email, password=None):
"""
Creates and saves a User with the given email and password.
"""
if not email:
raise ValueError('Users must have an email address')
user = self.model(
email=self.normalize_email(email),
)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, password):
"""
Creates and saves a superuser with the given email and password.
"""
user = self.create_user(email,
password=password,
)
user.is_admin = True
user.save(using=self._db)
return user
class MyUser(AbstractBaseUser):
email = models.EmailField(
verbose_name='email address',
max_length=255,
unique=True,
)
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
objects = MyUserManager()
USERNAME_FIELD = 'email'
def get_full_name(self):
# The user is identified by their email address
return self.email
def get_short_name(self):
# The user is identified by their email address
return self.email
def __str__(self): # __unicode__ on Python 2
return self.email
def has_perm(self, perm, obj=None):
"Does the user have a specific permission?"
# Simplest possible answer: Yes, always
return True
def has_module_perms(self, app_label):
"Does the user have permissions to view the app `app_label`?"
# Simplest possible answer: Yes, always
return True
#property
def is_staff(self):
"Is the user a member of staff?"
# Simplest possible answer: All admins are staff
return self.is_admin
login.html
<html>
<head>
<title>Login</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/smoothness/jquery-ui.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
{% load staticfiles %}
<link rel="stylesheet" type="text/css" href="{% static 'customauth/style.css' %}">
</head>
<body>
<div class="container">
<div id="loginbox" class="mainbox col-md-6 col-md-offset-3 col-sm-6 col-sm-offset-3">
<!--<div class="row">
<div class="iconmelon">
<object type="image/svg+xml" data="customauth/static/customauth/barbell.svg">Your browser does not support SVG</object>
</div>
</div>-->
<div class="panel panel-default" >
<div class="panel-heading">
<div class="panel-title text-center"><b>DATA STRONG</b></div>
</div>
<div class="panel-body" >
{% if form.errors %}
<p>Invalid email or password! Please try again.</p>
{% endif %}
<form name="form" id="form" class="form-horizontal" enctype="multipart/form-data" method="POST">
{% csrf_token %}
<div class="input-group">
<span class="input-group-addon"><i class="glyphicon glyphicon-user"></i></span>
<input id="user" type="text" class="form-control" name="email" value="" placeholder="Email">
</div>
<div class="input-group">
<span class="input-group-addon"><i class="glyphicon glyphicon-lock"></i></span>
<input id="password" type="password" class="form-control" name="password" placeholder="Password">
</div>
<div class="input-group checkbox">
<label><input name="remember" type="checkbox">Remember me</label>
</div>
<div class="form-group">
<!-- Button -->
<div class="col-sm-12 controls">
<button type="submit" class="btn btn-primary pull-right" value="{{ next }}"><i class="glyphicon glyphicon-log-in"></i> Log in</button>
</div>
</div>
</form>
</div> <!-----END OF BOOTSTAP CONTAINER----->
</div>
</div>
</div>
</body>
</html>
You should first create a Registration Form in forms.py, like this:
class RegistrationForm(forms.Form):
email = forms.EmailField(label='Email')
password = forms.CharField(label='Password', widget=forms.PasswordInput())
You should then import and pass this form to your template, so add this to your view:
# import the RegistrationForm (change AppName to the name of you app)
from AppName.forms import RegistrationForm
def login_user(request):
form = RegistrationForm() # add this
logout(request)
email = password = ''
if request.POST:
form = RegistrationForm(request.POST) # and add this
## rest of the code goes here ##
context = RequestContext(request, {
'state': state,
'email': email,
'form': form, # pass form to the front-end / template
})
return render_to_response('customauth/login.html', {}, context)
and make this your login.html:
{% if form.errors %}
{{ form.errors }} <!-- display the form errors if they exist -->
{% endif %}
<!-- display the form -->
<form action="/login" method="post">
{% csrf_token %}
{{ form }} <-- this displays all the form fields -->
<input type="submit" value="Submit" />
</form>
I want to create my own login page uses the e-mail address and password in django 1.7.
When complete box and I click "login" page back to the login page.
My view:
def get_user_by_email(email):
try:
return User.objects.get(email=email)
except User.DoesNotExist:
return None
def login_by_email(request):
email = request.POST.get('email')
password = request.POST.get('password')
username = get_user_by_email(email)
user = authenticate(username=username, password=password)
if user is not None:
if user.is_active():
login(request, email)
return HttpResponseRedirect(reverse("myapp:dashboard"))
return render_to_response('myapp/login.html', context_instance=RequestContext(request))
My url:
url(r'^login/$', views.login_by_email, name='login'),
My template login.html
{% block content %}
<form class="form-horizontal" name="LoginForm" action="{% url 'myapp:login' %}" method="post">
{% csrf_token %}
<div class="control-group">
<label class="control-label" for="email">Email</label>
<div class="controls">
<input type="text" id="email" value="{{email}}" placeholder="Email">
</div>
</div>
<div class="control-group">
<label class="control-label" for="password">Password</label>
<div class="controls">
<input type="password" name="password" id="password" placeholder="Password">
</div>
</div>
<div class="control-group">
<div class="controls">
<button type="submit" class="btn">Login</button>
</div>
</div>
</form>
{% endblock %}
This line:
username = get_user_by_email(email)
Should be:
user_instance = get_user_by_email(email)
if user_instance:
username = user_instance.username
You are passing the user object to authenticate and it isn't able to log the user in.
Also, when you call the login function, you should pass the user as parameter:
login(request, user)
You are currently passing the email (django can't handle it this way)
Refer to the auth docs for more detail on how to handle custom login mechanisms
EDIT: Here's the complete view code
def get_user_by_email(email):
try:
return User.objects.get(email=email)
except User.DoesNotExist:
return None
def login_by_email(request):
email = request.POST.get('email')
password = request.POST.get('password')
user_instance = get_user_by_email(email)
if user_instance:
username = user_instance.username
user = authenticate(username=username, password=password)
if user is not None:
if user.is_active:
login(request, user)
return HttpResponseRedirect(reverse("myapp:dashboard"))
return render_to_response('myapp/login.html', context_instance=RequestContext(request))