I'm using the normal development server for Django and i am building a simple app.
A user should be able to log in and change his email and password.
To understand the django system better, I decided to write the views and such myself, only using the contrib.auth library.
Now to the problem:
Once a user logs in and changes his password, he cannot login again, unless he logs into the standard django admin page before.
Here is my code:
the views.py
def login(request):
print("test")
if request.method == 'POST':
form = LoginForm(request.POST)
if form.is_valid():
username = form.cleaned_data['username']
password = form.cleaned_data['password']
user = authenticate(username=username, password=password)
if user is not None:
return HttpResponseRedirect('/accountManagement/home')
else:
form = LoginForm()
else:
HttpResponse("form is not valid")
else:
form = LoginForm()
return render(request, 'accountManagement/login.html', {'form': form})
def home(request):
print(request.user.username)
if request.user.is_authenticated:
passwordForm = ChangePasswordForm()
emailForm = ChangeEmailForm()
return render(request, 'accountManagement/home.html', {'passwordForm': passwordForm, 'emailForm': emailForm})
else:
return HttpResponseRedirect("/accountManagement/")
def change_password(request):
if request.user.is_authenticated:
if request.method == 'POST':
passwordForm = ChangePasswordForm(request.POST)
if passwordForm.is_valid():
oldPassword = passwordForm.cleaned_data['oldPassword']
newPassword = passwordForm.cleaned_data['newPassword']
newPasswordConfirmation = passwordForm.cleaned_data['newPasswordConfirmation']
if (newPassword == newPasswordConfirmation) and (request.user.check_password(oldPassword)):
request.user.set_password(newPassword)
request.user.save()
return HttpResponseRedirect("/accountManagement/logout")
else:
return HttpResponse("password change failed")
else:
return HttpResponse("password form not valid")
else:
return HttpResponse("request != POST")
else:
return HttpResponse("user ist not authenticated")
url.py:
urlpatterns = [
url(r'^$', views.login, name='login'),
url(r'^home', views.home, name='home'),
url(r'^changeEmail', views.change_email, name='changeEmail'),
url(r'^changePassword', views.change_password, name='changePassword'),
url(r'^logout', views.logout_view, name='logout'),
]
the forms:
class LoginForm(forms.Form):
username = forms.CharField(label='Username', max_length=20)
password = forms.CharField(label='Password', max_length=20)
class ChangeEmailForm(forms.Form):
newEmail = forms.CharField(label='New Email', max_length=50)
class ChangePasswordForm(forms.Form):
oldPassword = forms.CharField(label='Old Password', max_length=20)
newPassword = forms.CharField(label='New Password', max_length=20)
newPasswordConfirmation = forms.CharField(label='Confirm new Password', max_length=20)
Thanks for the help, really can't figure this one out.
Changing password destroy user authentication status, so you need re-authenticate him with new password again:
from django.contrib.auth import login
def change_password(request):
if request.user.is_authenticated:
if request.method == 'POST':
passwordForm = ChangePasswordForm(request.POST)
if passwordForm.is_valid():
oldPassword = passwordForm.cleaned_data['oldPassword']
newPassword = passwordForm.cleaned_data['newPassword']
newPasswordConfirmation =
passwordForm.cleaned_data['newPasswordConfirmation']
if (newPassword == newPasswordConfirmation)\
and (request.user.check_password(oldPassword)):
request.user.set_password(newPassword)
request.user.save()
# Re-authentication ===============================
# =================================================
user = authenticate(username=request.user.username,
password=NewPassword)
login(request, user)
# Why redirect to logout?!
return HttpResponseRedirect("/accountManagement/logout")
else:
return HttpResponse("password change failed")
else:
return HttpResponse("password form not valid")
else:
return HttpResponse("request != POST")
else:
return HttpResponse("user ist not authenticated")
Also I suggest you use CBV (Class based views) instead FBV (Function based views).
Any case you can use decorators #login_required and #require_http_methods in your view to remove is_authenticated and method != 'POST' logic.
from django.views.decorators.http import require_http_methods
from django.contrib.auth.decorators import login_required
#require_http_methods(["POST", ])
#login_required(redirect_field_name='my_redirect_field')
def change_password(request):
passwordForm = ChangePasswordForm(request.POST)
if passwordForm.is_valid():
oldPassword = passwordForm.cleaned_data['oldPassword']
newPassword = passwordForm.cleaned_data['newPassword']
newPasswordConfirmation =
passwordForm.cleaned_data['newPasswordConfirmation']
if (newPassword == newPasswordConfirmation)\
and (request.user.check_password(oldPassword)):
request.user.set_password(newPassword)
request.user.save()
# Re-authentication ===============================
# =================================================
user = authenticate(username=request.user.username,
password=NewPassword)
login(request, user)
# Why redirect to logout?!
return HttpResponseRedirect("/accountManagement/logout")
else:
return HttpResponse("password change failed")
else:
return HttpResponse("password form not valid")
Related
veiws.py
from django.shortcuts import render,redirect
from django.contrib.auth.models import User, auth
from django.contrib import messages
from travello.models import Destination
import traceback
from django.core.files.storage import FileSystemStorage
# Create your views here.
def login(request):
if request.method == 'POST':
username = request.POST['username']
password = request.POST['password']
user = auth.authenticate(username=username, password=password)
if user is not None:
auth.login(request,user)
return redirect("/")
else:
messages.info(request,'invalid credentials')
return redirect('login')
else:
return render(request, 'login.html')
def register(request):
if request.method == "POST":
first_name = request.POST.get('first_name')
last_name = request.POST.get('last_name')
username = request.POST.get('username')
email = request.POST.get('email')
password1 = request.POST.get('password1')
password2 = request.POST.get('password2')
if password1 == password2:
if User.objects.filter(username=username).exists():
messages.info(request,'Username taken')
return redirect('register')
elif User.objects.filter(email=email).exists():
messages.info(request,'EMAIL taken')
return redirect('register')
else:
user = User.objects.create_user(username=username, email=email, password=password1, first_name=first_name, last_name=last_name)
user.save();
print("User created")
return redirect('login')
else:
messages.info(request,'password not matching...')
return redirect('register')
else :
return render(request, 'register.html')
def logout(request):
auth.logout(request)
return redirect('/')
def postdestination(request):
if request.method == 'POST':
try:
f = request.FILES["img"]
fs = FileSystemStorage()
filename = fs.save(f.name, f)
uploaded_file_url = fs.url(filename)
name = request.POST['name']
# img = request.POST['img']
description = request.POST['description']
price = request.POST['price']
offer = request.POST.get('offer')
if offer == "on":
offer = True
else:
offer = False
d = Destination.objects.create(name=name, desc=description,img=uploaded_file_url,price=price,offer=offer)
d.save()
except Exception as e:
traceback.print_exc()
return redirect('/')
else:
return render(request, 'post_destination.html')
While registering this error is occurring. I'm using postgresql as DBMS .
Request Method: POST
Request URL: http://localhost:8000/accounts/register
Django Version: 3.2
Exception Type: ValueError
ValueError at /accounts/register
The given username must be set
You are using request.POST but you are not passing any form to it after.
You should explicitly pass the form in the different requests so that django will know what to handle.
I am developing a feature, when a user registers it automatically logs the user in
but i get 'AnonymousUser' object has no attribute '_meta' error.
but when i use the same code to login the user it works fine.
my forms.py:
from django.contrib.auth.forms import UserCreationForm
from django import forms
from django.core.exceptions import ObjectDoesNotExist
from django.contrib.auth.models import User
from .models import *
class RegisterForm(forms.Form):
fname = forms.CharField(error_messages=(), widget=forms.TextInput(attrs={"class":"fname entry", "placeholder":"First Name"}), required=True)
lname = forms.CharField(error_messages=(), widget=forms.TextInput(attrs={"class":"lname entry", "placeholder":"Last Name"}), required=True)
phone = forms.CharField(error_messages=(), widget=forms.TextInput(attrs={"class":"phone entry", "placeholder":"Phone Number"}), required=True)
password = forms.CharField(widget=forms.PasswordInput(attrs={"class":"password entry", "placeholder":"Password", "autocomplete":"off"}), required=True)
password2 = forms.CharField(widget=forms.PasswordInput(attrs={"class":"password entry", "placeholder":"Confirm Password", "autocomplete":"off"}), required=True)
def clean(self, *args, **kwargs):
fname = self.cleaned_data.get("fname")
lname = self.cleaned_data.get("lname")
phone = self.cleaned_data.get("phone")
password = self.cleaned_data.get("password")
password2 = self.cleaned_data.get("password2")
if phone and password and fname and lname and password2:
try:
user = User.objects.get(phone=PhoneNumber.objects.get(number=phone))
if user:
raise forms.ValidationError("user exists login instead")
except ObjectDoesNotExist:
pass
if password!=password2:
raise forms.ValidationError("passwords didn't match")
else:
if len(password)<8:
raise forms.ValidationError("short password! password should be longer than 8")
in my forms i have a registration form which does not inherit from django's user creation form.
my views.py:
def registerView(request):
if request.method == "POST":
form = RegisterForm(request.POST)
if form.is_valid():
fname = form.cleaned_data.get("fname")
lname = form.cleaned_data.get("lname")
username = generate_username(fname, lname)
phone = form.cleaned_data.get("phone")
u = User.objects.create_user(email="", first_name=fname, last_name=lname, username=username, is_active=False)
u.set_password(form.cleaned_data.get("password"))
u.save()
p = PhoneNumber(user=u, number=phone)
p.save()
phone = PhoneNumber.objects.get(number=phone)
u = User.objects.get(phone=phone)
userLogin = authenticate(username=username, password=u.password)
login(request, userLogin)
return redirect('home')
else:
form = RegisterForm()
return render(request, 'main/register.html', {'form':form})
my loginView:
def loginView(request):
if request.method == "POST":
form = LoginForm(request.POST)
if form.is_valid():
phone = PhoneNumber.objects.get(number=form.cleaned_data.get('phone'))
u = User.objects.get(phone=phone)
user = authenticate(username=u.username, password=form.cleaned_data.get('password'))
login(request, user, backend='django.contrib.auth.backends.ModelBackend')
print('success')
return redirect('home')
else:
form = LoginForm()
return render(request, 'main/login.html', {'form':form})
i have imported everything i need. the same code works with the loginView function but it doesn't work on registerView
What should i do to fix this?
You have this line in your view:
userLogin = authenticate(username=username, password=u.password)
The point to be noted here is that u is an instance of the user model and u.password will give the hashed password while authenticate expects it to be a raw password and hence returns None. In fact you don't even need to use authenticate while registering as you already have the user instance:
def registerView(request):
if request.method == "POST":
form = RegisterForm(request.POST)
if form.is_valid():
fname = form.cleaned_data.get("fname")
lname = form.cleaned_data.get("lname")
username = generate_username(fname, lname)
phone = form.cleaned_data.get("phone")
# removed `is_active=False` as per comment by #Nahu Gere
user = User.objects.create_user(email="", first_name=fname, last_name=lname, username=username) # better variable name
user.set_password(form.cleaned_data.get("password"))
user.save()
phone = PhoneNumber(user=user, number=phone)
phone.save()
login(request, user) # Directly use saved user instance
return redirect('home')
else:
form = RegisterForm()
return render(request, 'main/register.html', {'form':form})
I got this error because In my register view, I had this code:
user.is_active = False
user.save()
then I had so the user got logged in automatically after registering an account.
user = authenticate(username=user.username, password=raw_password)
login(request, user)
I solved it by commenting out the auto login
# user = authenticate(username=user.username, password=raw_password)
# login(request, user)
Upon registration I check the user_type and move the user to one of three web pages.
It is showing the correct page layout but the url stays the same as the registration page.
EG: url says "http://127.0.0.1:8000/users/register/"
Page shows: "user type 1 information"
I thought using redirect should change the url but it doesn't seem to be working.
views.py:
def register(request):
if request.method == 'POST':
form = RegisterForm(data=request.POST)
if form.is_valid():
# profile = form.save(commit=False)
# profile.user = request.user
# profile.save()
user = form.save()
profile = user.userprofile
user_group = form.cleaned_data.get('user_type')
profile.user_type = user_group
profile.save()
# form.save()
username = form.cleaned_data.get('username')
password = form.cleaned_data.get('password1')
user_group = form.cleaned_data.get('user_type')
user = authenticate(username = username, password = password)
login(request, user)
print(user_group)
print(type(user_group))
if user_group == '1':
return HttpResponseRedirect("/users/business/")
# return
# HttpResponseRedirect('http://127.0.0.1:8000/users/business/')
# return HttpResponseRedirect(reverse('users:business'))
# return redirect(request, 'users/business.html')
elif user_group == '2':
return redirect(request, 'users/student.html')
elif user_group == '3':
return redirect(request, 'users/tourist.html')
# else:
# return redirect('main:index')
else:
print(RegisterForm.errors)
else:
form = RegisterForm()
def business_view(request):
# return redirect(request, 'users/business.html')
# return HttpResponseRedirect('users/business.html')
# return redirect('/users/business/')
return redirect('users/business')
def student_view(request):
return redirect(request, 'users/student.html')
def tourist_view(request):
return redirect(request, 'users/tourist.html')
urls.py
urlpatterns = [
# Login page
#url(r'^login/$', login, {'template_name': 'users/login.html'},
name='login'),
url(r'^login/$', login, {'template_name': 'users/login.html'},
name='login'),
#url(r'^login/$', views.log_in, name='login'),
# Register page
url(r'^register/$', views.register, name='register'),
# Business page
#url(r'^business/$', views.business_view, name='business'),
url(r'^$',views.business_view),
# Student page
url(r'^student/$', views.student_view, name='student'),
# Tourist page
url(r'^tourist/$', views.tourist_view, name = 'tourist'),
]
Thanks for any help.
Use urlname only in redirect argument, i.e. to redirect on student page use return redirect('student') (name defined while defining urls). Eg.
if user_group == '2':
return redirect('student')
Also in your views where you want to show html page, use render instead. Eg.
from django.shorcuts import render
def student_view(request):
return render(request, 'users/student.html')
In my Django app I create a User from django.contrib.auth.models, and I am using request.user in multiple view functions without a problem. In one of my view functions I change the user password, save the user, and redirect the client to another view function. Once I try to get the user from the request in that function, the user is Anonymous. After using User.set_password() or redirecting, does it take the user out of the session ?
views.py
from django.contrib import messages
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.forms import AuthenticationForm, UserCreationForm
from django.core.urlresolvers import reverse
from django.http import HttpResponseRedirect, HttpResponse
from django.shortcuts import render
from .models import Profile
from .forms import ProfileForm, PasswordForm
def sign_in(request):
form = AuthenticationForm()
if request.method == 'POST':
form = AuthenticationForm(data=request.POST)
if form.is_valid():
if form.user_cache is not None:
user = form.user_cache
if user.is_active:
login(request, user)
return HttpResponseRedirect(
reverse('home') # TODO: go to profile
)
else:
messages.error(
request,
"That user account has been disabled."
)
else:
messages.error(
request,
"Username or password is incorrect."
)
return render(request, 'accounts/sign_in.html', {'form': form})
def sign_up(request):
form = UserCreationForm()
if request.method == 'POST':
form = UserCreationForm(data=request.POST)
if form.is_valid():
form.save()
user = authenticate(
username=form.cleaned_data['username'],
password=form.cleaned_data['password1']
)
new_profile = Profile.objects.create(user=user)
login(request, user)
messages.success(
request,
"You're now a user! You've been signed in, too."
)
return HttpResponseRedirect(reverse('home')) # TODO: go to profile
return render(request, 'accounts/sign_up.html', {'form': form})
def sign_out(request):
logout(request)
messages.success(request, "You've been signed out. Come back soon!")
return HttpResponseRedirect(reverse('home'))
def profile(request):
user = request.user
try:
account = Profile.objects.get(user=user)
except Profile.DoesNotExist:
account = None
print(account.first_name)
context = {'account': account}
return render(request, 'accounts/profile.html', context)
def edit(request):
account = Profile.objects.get(user=request.user)
form = ProfileForm(instance=account)
if request.method == 'POST':
account = Profile.objects.get(user=request.user)
form = ProfileForm(request.POST, request.FILES)
if form.is_valid():
account.first_name = form.cleaned_data['first_name']
account.last_name = form.cleaned_data['last_name']
account.email = form.cleaned_data['email']
account.bio = form.cleaned_data['bio']
account.avatar = form.cleaned_data['avatar']
account.year_of_birth = form.cleaned_data['year_of_birth']
account.save()
context = {'account': account}
return HttpResponseRedirect('/accounts/profile')
else:
x =form.errors
context = {'form': form, 'errors': form.errors}
return render(request, 'accounts/edit.html', context)
else:
context = {'form': form}
return render(request, 'accounts/edit.html', context)
def change_password(request):
user = request.user
if request.method == 'POST':
form = PasswordForm(request.POST)
if form.is_valid():
cleaned_data = form.cleaned_data
if not user.check_password(cleaned_data['old_password']):
form.add_error('old_password', 'Old password is incorrect')
context = {'form': form}
return render(request, 'accounts/password.html', context)
try:
user.set_password(cleaned_data['new_password'])
user.save()
return HttpResponseRedirect('/accounts/profile')
except Exception as e:
form = PasswordForm()
context = {'form': form}
return render(request, 'accounts/password.html', context)
else:
form = PasswordForm()
context = {'form': form}
return render(request, 'accounts/password.html', context)
forms.py
class PasswordForm(forms.Form):
old_password = forms.CharField(max_length=200)
new_password = forms.CharField(max_length=200)
confirm_password = forms.CharField(max_length=200)
def clean(self, *args, **kwargs):
cleaned_data = super(PasswordForm, self).clean()
if 'new_password' in cleaned_data:
new_password = cleaned_data['new_password']
else:
new_password = None
if 'confirm_password' in cleaned_data:
confirm_password = cleaned_data['confirm_password']
else:
confirm_password = None
if confirm_password and new_password:
if new_password != confirm_password:
self.add_error('confirm_password', 'Passwords do not match')
Yes. See the documentation about session invalidation on password change. To fix it, see this bit in particular:
The default password change views included with Django, PasswordChangeView and the user_change_password view in the django.contrib.auth admin, update the session with the new password hash so that a user changing their own password won't log themselves out. If you have a custom password change view and wish to have similar behavior, use the update_session_auth_hash() function.
hi i a working on a project for that i have made login and registration of a user. now i want to show full profile of user.since get_profile is not working anymore so how can i get full profile of a user
my models.py
class Consultants(models.Model):
consul_id=models.IntegerField(default=0,primary_key=True)
first_name=models.CharField(max_length=255,blank=True,null=True)
last_name=models.CharField(max_length=255,blank=True,null=True)
email=models.EmailField(max_length=255,blank=True,null=True)
username=models.CharField(max_length=255,blank=True,null=True)
password=models.CharField(max_length=50,blank=True,null=True)
last_login=models.DateTimeField(default=datetime.now,blank=True,null=True)
is_active=models.BooleanField(default=False)
def __str__(self):
return self.first_name
views.py for login and registration
def register(request):
context = RequestContext(request)
registered = False
if request.method == 'POST':
# user_form = UserForm(data=request.POST)
consultant_form = ConsultantsForm(data=request.POST)
if consultant_form.is_valid():
consultant = consultant_form.save(commit=False)
consultant.save()
registered = True
else:
print consultant_form.errors
else:
consultant_form = ConsultantsForm()
return render_to_response(
'register.html',
{'consultant_form': consultant_form, 'registered': registered},
context_instance=RequestContext(request))
def login_user(request):
context = RequestContext(request)
if request.method == 'POST':
username = request.POST['username']
password = request.POST['password']
print type(username)
print "username",username
try:
user = Consultants.objects.get(Q(username= username) & Q(password= password))
print 'chala'
if user.is_active:
user.backend = 'django.contrib.auth.backends.ModelBackend'
login(request, user)
return HttpResponse("welcome......you are succesfuly log in")
else:
return HttpResponse("Your UkKonnect account is disabled.")
except ObjectDoesNotExist:
return HttpResponse("INvalid User")
else:
return render_to_response('login.html', {}, context)
i want to make def full_profile and def edit_profile.
How can i get logged in user consul_id??
please help me
Not sure that I understand you problem well.. Take a look at recommended way of extending User model:
https://docs.djangoproject.com/en/dev/topics/auth/customizing/#extending-the-existing-user-model
from django.contrib.auth.models import User
class Employee(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
department = models.CharField(max_length=100)
Then you can do:
u = User.objects.get(username='fsmith')
freds_department = u.employee.department
In your case it would be:
class Consultant(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
*your fields here*
Now you can use standard authentication forms and methods
You always can obtain consultant data as:
request.user.consultant