Django not authenticating using custom User model - python

I am trying to authenticate users against an existing database. I can authenticate the user with their email and password combination but I cannot save the authorisation, meaning the user is not actually logged in.
I know this because in Template.html, it is not showing the correct options after login when I call {% if user and not user.is_anonymous %}
I believe the fault is coming from this line in views.py
auth_login(request, user)
Views.py
from django.contrib.auth import logout as auth_logout
from django.contrib.auth import login as auth_login
from django.contrib.auth import authenticate
...
def login_email(request):
if request.method == 'POST':
email = request.POST.get('email')
password = hashlib.md5(request.POST.get('password')).hexdigest()
#db query to check if email and password combination exist
user = Users.objects.get(email=email,password=password)
if user is not None:
user.backend = 'django.contrib.auth.backends.ModelBackend'
auth_login(request, user)
return redirect('/personalised')
else: #failed to return to login page
return render(request, 'login.html',{})
#invalid POST request recieved
else:
return render(request,"login.html",{})
login.html
<form action="/login_email/" method="POST">
{% csrf_token %}
<div class="form-group">
<label for="email">Email address</label>
<input type="email" name="email" class="form-control" id="email" placeholder="Email">
</div>
<div class="form-group">
<label for="email">Password</label>
<input type="password" name="password" class="form-control" id="password" placeholder="Password">
</div>
<button type="submit" class="btn btn-info">Submit</button>
</form>
Models.py
class Users(models.Model):
visitorid = models.CharField(db_column='visitorID', max_length=80) # Field name made lowercase.
name = models.CharField(max_length=255)
source = models.CharField(max_length=4)
visits = models.IntegerField()
last_visit = models.CharField(max_length=10)
email = models.CharField(max_length=255)
unsubscribe = models.CharField(max_length=1)
twitter = models.CharField(max_length=100)
password = models.TextField()
.....
template.py
{% if user and not user.is_anonymous %}
<li>My Feed </li>
<li>Trending</li>
<li>Your Saves</li>
<li>Logout </li>
{% else %}
<button type="button" class="btn btn-success navbar-btn">Sign in with Email</button>
{% endif %}

Do not use this code:
email = request.POST.get('email')
password = hashlib.md5(request.POST.get('password')).hexdigest()
#db query to check if email and password combination exist
user = Users.objects.get(email=email,password=password)
Instead use the authenticate method. It returns a User
user = authenticate(email=email, password=password)
This assumes that you have an appropriate auth backend setup.

Related

Django form errors not showing when use id_<field-name>

I'm a beginner in Django, I try to use for="id_<field-name>" method to create a signup form interface, but the default validation like "This field is required." or "This username already exists" is not showing. I don't want to use {{ form.as_p }} because I want to separate the field. The registration still working if i input the true the valid things.
HTML
<form method="POST" class="register-form" id="register-form" enctype="multipart/form-data" >
{% csrf_token %}
<div class="form-group">
<label for="id_username"><i class="zmdi zmdi-account material-icons-name"></i></label>
<input type="text" name="username" id="username" placeholder="Username"/>
</div>
<div class="form-group">
<label for="id_email"><i class="zmdi zmdi-email"></i></label>
<input type="email" name="email" id="email" placeholder="Your Email" />
</div>
<div class="form-group">
<label for="id_password"><i class="zmdi zmdi-lock"></i></label>
<input type="password" name="password" id="password" placeholder="Password"/>
</div>
<div class="form-group">
<input type="checkbox" name="agree-term" id="agree-term" class="agree-term" />
<label for="agree-term" class="label-agree-term"><span><span></span></span>I agree all statements in Terms of service</label>
</div>
<div class="form-group form-button">
<input type="submit" name="signup" id="signup" class="form-submit" value="Register"/>
</div>
</form>
views.py
def register(request):
registered = False
if request.method == 'POST':
# Get info from "both" forms
# It appears as one form to the user on the .html page
user_form = UserForm(data=request.POST)
profile_form = UserProfileInfoForm(data=request.POST)
# Check to see both forms are valid
if user_form.is_valid() and profile_form.is_valid():
# Save User Form to Database
user = user_form.save()
# Hash the password
user.set_password(user.password)
# Update with Hashed password
user.save()
# Now we deal with the extra info!
# Can't commit yet because we still need to manipulate
profile = profile_form.save(commit=False)
# Set One to One relationship between
# UserForm and UserProfileInfoForm
profile.user = user
# Check if they provided a profile picture
if 'profile_pic' in request.FILES:
print('found it')
# If yes, then grab it from the POST form reply
profile.profile_pic = request.FILES['profile_pic']
# Now save model
profile.save()
# Registration Successful!
registered = True
else:
# One of the forms was invalid if this else gets called.
print(user_form.errors,profile_form.errors)
else:
# Was not an HTTP post so we just render the forms as blank.
user_form = UserForm()
profile_form = UserProfileInfoForm()
# This is the render and context dictionary to feed
# back to the registration.html file page.
return render(request,'basic_app/registration.html',
{'user_form':user_form,
'profile_form':profile_form,
'registered':registered,
})
forms.py
from django import forms
from django.contrib.auth.models import User
from .models import UserProfileInfo, TeaProfileInfo
class UserForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput())
class Meta():
model = User
fields = ('username','email','password')
My signup page interface
A quick way to validate your form by adding the following to your form.py
def clean(self):
super(UserForm, self).clean()
username = self.cleaned_data.get('username')
email = self.cleaned_data.get('email')
password = self.cleaned_data.get('password')
if username == "" or email == "" or password == "":
raise forms.ValidationError(['This field is required.'])
In your HTML make sure to add the following after/before each field
{{ username.errors }}
{{ email.errors }}
{{ password.errors }}

Django 2.1.4 Registration Form + Login Page

Hi I am new to Django and need help with registration form and login. I am able to register and able to see the user credentials registered under admin register model. However, i tried to take the user-credentials in the database and then want to do a login, but unable to do so. Can someone help please.
models.py
class register(models.Model):
name = models.CharField(max_length=250)
username = models.CharField(max_length=20)
password = models.CharField(max_length=20)
occupation = models.CharField(max_length=100)
def __unicode__(self):
return str(self.username)
Views.py
#register
def registerForm(request):
if request.method == 'POST':
if request.POST.get('name') and request.POST.get('username') and request.POST.get('password') and request.POST.get('occupation'):
reg = register()
reg.name = request.POST['name']
reg.username = request.POST['username']
reg.password = request.POST['password']
reg.occupation = request.POST['occupation']
reg.save()
return render(request, 'login.html')
else:
return render(request, 'register.html')
#Login
def Login(request):
if request.method == 'POST':
if request.POST.get('username') and request.POST.get('password'):
usr_login = register()
usr_login.username = request.POST['username']
usr_login.password = request.POST['password']
usr_login.user = authenticate(username=username, password=password)
if usr_login.user:
login(request, usr_login.user)
return HttpResponseRedirect('/forum/')
else:
error = "Username and Password are invalid. Please try again."
return render(request, 'login.html')
else:
return render(request, 'login.html')
login.html
<form method="post" action="/forum/">
{% csrf_token %}
<div class="form-group">
<label for="username">Username:</label>
<input type="username" class="form-control" id="username" placeholder="Enter username" required="required">
</div>
<div class="form-group">
<label for="pwd">Password:</label>
<input type="password" class="form-control" id="pwd" placeholder="Enter password" required="required">
</div>
<div class="row">
<div class="col" align="center">
<div class="form-group form-check">
<label class="form-check-label">
<input class="form-check-input" type="checkbox"> Remember me
</label>
</div>
<button type="submit" class="btn btn-primary" value="login">Submit</button><br><br>
Not yet registered? Register Here.
</form>
urls.py
# login
url(r'^login/$', views.Login, name='login'),
# register
url(r'^registeration/$', views.registerForm, name='registeration'),
You are trying to authenticate the user using the django builtin authentication backend but you are not using the django User model. In your case you have to create custom authentication logic. I strongly suggest you to hash the user's password.
If you want to use the builtin auth framework you check out the documentation for more information https://docs.djangoproject.com/en/2.1/ref/contrib/auth/

Already registered user name can be registered

Already registered user name can be registered in user creation form. I'm making Django application.
I wrote in views.py
def regist(request):
regist_form = RegisterForm(request.POST or None)
context = {
'regist_form': regist_form,
}
return render(request, 'registration/regist.html', context)
def regist_save(request):
regist_form = RegisterForm(request.POST or None)
if request.method == "POST" and regist_form.is_valid():
regist = regist_form.save(commit=False)
regist.is_staff = True
regist.save()
advertisements = Advertisement.objects.all()
return render(request, 'registration/detail.html', {'advertisements': advertisements})
in regist.html
<form class="form-horizontal" action="/accounts/regist_save/" method="POST">
<div class="form-group-lg">
<label for="id_username">Username</label>
{{ regist_form.username }}
<p class="help-block">{{ regist_form.username.help_text }}</p>
</div>
<div class="form-group-lg">
<label for="id_email">Email</label>
{{ regist_form.email }}
<p class="help-block">{{ regist_form.email.help_text }}</p>
</div>
<div class="form-group-lg">
<label for="id_password">Password</label>
{{ regist_form.password1 }}
<p class="help-block">{{ regist_form.password1.help_text }}</p>
</div>
<div class="form-group-lg">
<label for="id_password">Password(Confirmation)</label>
{{ regist_form.password2 }}
<p class="help-block">{{ regist_form.password2.help_text }}</p>
</div>
<div class="form-group-lg">
<div class="col-xs-offset-2">
<button type="submit" class="btn-lg regist">Register</button>
<input name="next" type="hidden" />
</div>
</div>
{% csrf_token %}
</form>
in forms.py
class RegisterForm(UserCreationForm):
class Meta:
model = User
fields = ('username', 'email','password1','password1',)
def __init__(self, *args, **kwargs):
super(RegisterForm, self).__init__(*args, **kwargs)
self.fields['username'].widget.attrs['class'] = 'form-control'
self.fields['email'].widget.attrs['class'] = 'form-control'
self.fields['password1'].widget.attrs['class'] = 'form-control'
self.fields['password2'].widget.attrs['class'] = 'form-control'
Now in this user registration form, if I write already registered user name&email&password, these data is not registered but detail.html is load. I wanna show alert if I do so like "this user name is already registered". Why isn't my web page not my ideal one? Why can I resist already registered user name in my site? How should I fix this? I did not make User model in models.py.
from django.contrib.auth.models import User
from django.contrib import messages
from django.db.models import Q
if request.method == "POST" and regist_form.is_valid():
try:
username = form.cleaned_data.get('username', None)
email = form.cleaned_data.get('email', None)
# if username or email already exist in the User table
# if you want to use the user object you can make it
# if you want to check username and email with or, then it would work
user = User.objects.get(Q(username=username) | Q(email=email))
# if you want to check username and email with and, then it would work
user = User.objects.get(username=username, email=email)
# else if you have no username but only email you just only filter for email
user = User.objects.get(email=email)
# else if no need for user detail, you can do this
User.objects.get(Q(username=username) | Q(email=email))
messages.warning(request, 'That detailed use is already available.')
# return to register form / template page
# whatever your page is
except User.DoesNotExist:
# save the user
regist = regist_form.save(commit=False)
regist.is_staff = True
regist.save()
I suggest using a custom model and extending auth. By default if unique is set to true, django fill raise a form error during submit itself.
In models.py
class User(AbstractUser):
"""User model."""
username = models.CharField(max_length=128, unique=True)
email = models.EmailField(_('email address'), unique=True)
def __str__(self):
return self.username
PS: Override where ever required. Also suggest looking in the django tutorials, and simpleisbetterthancomplex. Mr Vitor has an easy tutorial

Login and Logout view not working in django auth system

I am using the Django auth system for my app. I have made a CustomUser table using AbstractUser functionality to add some more fields.
//models.py
from django.contrib.auth.models import AbstractUser
from django.contrib.sessions.models import Session
class CustomUser(AbstractUser):
addr1= models.CharField(max_length=20)
addr2= models.CharField(max_length=20)
city= models.CharField(max_length=20)
state= models.CharField(max_length=20)
class UserSession(models.Model):
user= models.ForeignKey(settings.AUTH_USER_MODEL)
session=models.ForeignKey(Session)
//views.py
from .models import UserSession
from django.contrib.auth.signals import user_logged_in
def login(request):
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('/Student_home.html') # Redirect to a success page.
else:
return HttpResponse("disabled account") # Return a 'disabled account' error message
else:
return HttpResponse("invalid login") # Return an 'invalid login' error message.
def logout(request):
logout(request)
return HttpResponseRedirect('/Student_home.html') # Redirect to a success page.
def user_logged_in_handler(sender,request,user, **kwargs):
UserSession.objects.get_or_create(
user= user,
session_id= request.session.session_key
)
user_logged_in.connect(user_logged_in_handler, sender=CustomUser)
def delete_user_sessions(CustomUser):
user_sessions=UserSession.objects.filter(user=CustomUser)
for user_session in user_sessions:
user_session.session.delete()
//forms.py
from django.contrib.auth.forms import AuthenticationForm
from django import forms
class LoginForm(AuthenticationForm):
username = forms.CharField(label="Username", max_length=30,
widget=forms.TextInput(attrs={'class': 'form-control', 'name': 'username'}))
password = forms.CharField(label="Password", max_length=30,
widget=forms.TextInput(attrs={'class': 'form-control', 'name': 'password'}))
//project/urls.py(the outer one)
from django.contrib.auth import views
from student.forms import LoginForm
url(r'^login/$', views.login, {'template_name': 'login.html', 'authentication_form': LoginForm}, name='login'),
url(r'^logout/$', views.logout, {'next_page': '/login'}),
//login.html
<div class="container">
<section id="content">
<form action="{% url 'login' %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
<h1>Login Form</h1>
<div class="imgcontainer">
<img src="{% static 'student/patient.jpg' %}" alt="Avatar" class="avatar">
</div>
<div class="username">
{{ form.username.label_tag }}
{{ form.username }}
</div>
<div class="password">
{{ form.password.label_tag }}
{{ form.password }}
</div>
<div class="submitb">
<input type="submit" value="Log In" name="mybtn">
</div>
<div class="resetb">
<input type="submit" value="Reset">
Forgot password?
</div>
<input type="hidden" name="next" value="{{ next }}" />
</form>
</section>
</div>
//settings.py
LOGIN_REDIRECT_URL = '/login/sample'
The login system and authentication system is working all fine. But here is the problem. It doesn't take any action when the user can't log in (wrong username and password). But it does gets redirected to 'sample' page which I guess is dut to the thing in settings.py. Also the user is not redirected to any page when the user is logged out although I have specified that it should be redirected to a home page. I think the control is not getting inside the 'login' and 'logout' view. Also the sessions are also not getting deleted when a user logs out as these sessions create and delete on the 'login()' and 'logout()' functions of the django auth system.
What is wrong here?

Django save user profile manually

I have created a Profile and attached to user model using OneToOneField. I have a registration form where user enters input which corresponds to user and profile. Django provides User.objects.create_user to save fields which are related to User model, but i don't know how to save details of Profile model manually.
Here is my code:
models.py
from django.db import models
from django.contrib.auth.models import User
def Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
full_name = models.CharField(max_length=150, required=True)
# lot more fields here
views.py
#csrf_protect
def register(request):
if request.method == 'POST':
full_name = request.POST.get('full_name', '')
username = request.POST.get('username', '')
password = request.POST.get('password', '')
User.objects.create_user(username=username, password=password)
# how to save Profile full_name here
return render(request, 'register.html')
register.html
<form method="post" action="/register/">{% csrf_token %}
<div class="form-group">
<label for="full_name">Name</label>
<input type="text" name="full_name" id="full_name">
</div>
<div class="form-group">
<label for="username">Username</label>
<input type="text" name="username" value="" id="username">
</div>
<div class="form">
<label for="password">Password</label>
<input type="pass" name="password" value="" id="password">
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
1) How can i save full_name of Profile model in views.py ? Can I do this without creating form class for every model in the future that want to save or Signals?
2) Do I need to change auth_user_model in settings.py in order to save profile details manually?
3) How to validate the fields without creating a new Form class?
#csrf_protect
def register(request):
if request.method == 'POST':
full_name = request.POST.get('full_name', '')
username = request.POST.get('username', '')
password = request.POST.get('password', '')
user = User.objects.create_user(username=username, password=password)
Profile.objects.create(user=user,full_name=full_name)
# how to save Profile full_name here
return render(request, 'register.html')
you can use the created user instance to create the profile associated with that user

Categories

Resources