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.
Related
my from is not sending data to database
here is my view.py and form.py
And yet they are no error reported on my console
views.py
def register(request):
if request.method == 'POST':
form = RegistrationForm(request.POST)
return redirect('../login/')
else:
form = RegistrationForm()
args = {'form': form}
return render(request, 'account/register.html', args)
forms.py
class RegistrationForm(UserCreationForm):
# first_name forms.CharField(... that i cut here to win some space
def save(self, commit=True):
user = super(RegistrationForm, self).save(commit=False)
user.email = self.cleaned_data['email']
user.first_name = self.cleaned_data['first_name']
user.last_name = self.cleaned_data['last_name']
if commit:
user.save()
return user
You forgot to call form.save() in your view. That's why your form is never saved.
Fix:
def register(request):
if request.method == 'POST':
form = RegistrationForm(request.POST)
form.save() # <- ATTENTION.
return redirect('../login/')
else:
form = RegistrationForm()
return render(request, 'account/register.html', {
'form': form,
})
Side notes
Don't hardcode the redirect path (i.e. ../login). In your urls.py file, give the url a name (e.g. path('login/', views.my_login, name='my_login')), and use the name to do the redirect (e.g. return redirect('my_login').
authenticate is not working , the user=authenticate(username=username,password=password) is returning None.
the user is none here and thus nothing is working
def homepage(request):
if request.method == "POST":
if "form2" in request.POST:
form = Userform(request.POST)
if form.is_valid():
user=form.save()
print(user.password)
login(request,user)
return redirect("main:dashboard")
else:
messages.error(request,'invalid entry')
return redirect("main:homepage")
elif "form1" in request.POST:
username=request.POST["email1"]
password=request.POST["password1"]
print(username)
print(password)
user=authenticate(username=username,password=password)
print(user)
if user is not None:
print("hello")
login(request,user)
return redirect("main:dashboard")
else:
messages.error(request,'user doesnot exist')
return redirect("main:homepage")
form = Userform
return render(request,
"index.html",{"form":form}
)
It seems like missing request in authenticate(). Try adding that and see.
user=authenticate(request, username=username, password=password)
Example:
from django.shortcuts import render
from django.http import HttpResponse
from django.contrib.auth import authenticate, login
<<import LoginForm/UserForm>>
def user_login(request):
if request.method == 'POST':
form = LoginForm(request.POST)
if form.is_valid():
cd = form.cleaned_data
user = authenticate(request,
username=cd['username'],
password=cd['password'])
if user is not None:
if user.is_active:
login(request, user)
return HttpResponse('Authenticated Successfully')
else:
return HttpResponse('Disabled Account')
else:
return HttpResponse('Invalid login')
else:
form = LoginForm()
return render(request, 'account/auth/login.html', {'form': form})
I am doing a basic user creation using the built-in UserCreationForm in Django.
Here is my views.py:
def user_register(request):
if request.method == "POST":
form = UserCreationForm(request.POST)
if form.is_valid():
form.save()
username = form.cleaned_data['username']
raw_password = form.cleaned_data['password1']
user = User.objects.create_user(username=username)
if raw_password:
user.set_password(raw_password)
else:
user.set_unusable_password()
user.save()
return redirect('home')
else:
form = UserCreationForm()
return render(request, 'registration/register.html', {'form': form})
However, after registering a user and being redirected to home, the number of Users seen in my Admin page has not changed; no User has been created.
Any idea what I am doing wrong here?
Try:
from django.contrib.auth import login, authenticate
from django.contrib.auth.forms import UserCreationForm
from django.shortcuts import render, redirect
from django.contrib.auth.models import User
def user_register(request):
if request.method == 'POST':
form = UserCreationForm(request.POST)
if form.is_valid():
username = form.cleaned_data['username']
password = form.cleaned_data['password1']
user=User.objects.create_user(username=username, password=password)
user.save()
#Below 2 lines, if you want user to get logged in
user = authenticate(username=username, password=password)
login(request, user)
return redirect('home')
else:
form = UserCreationForm()
return render(request, 'registration/register.html', {'form': form})
don't know why you can redirected to home with no use create,but you should deal with the situation form is not vaild and remove form.save() from form.is_valid() block like:
form = UserCreationForm(request.POST)
if form.is_valid():
# remove form.save()
....
else:
print(form.errors.as_text())
return render(request, 'registration/register.html', {'form': form})
or override save method for UserCreationForm like i do:
def save(self, commit=True):
user = super(UserCreationForm, self).save(commit=False)
user.set_password(self.cleaned_data["password1"])
if commit:
user.save()
return user
the full demo is:
from django.views.generic import *
class RegisterView(FormView):
template_name = 'registration/register.html'
form_class = UserCreationForm
success_url = reverse_lazy('home')
def form_valid(self, form):
form.save()
return HttpResponseRedirect(self.get_success_url())
forms.py
class UserCreationForm(forms.ModelForm):
error_messages = {
'duplicate_username': u"duplicate username",
'password_mismatch': u"password_mismatch",
'duplicate_email': u'duplicate email'
}
username = forms.RegexField(
max_length=30,
regex=r'^[\w.#+-]+$',
error_messages={
'invalid': u"onlay can contaions symbol #/./+/-/_",
'required': u"required"
},
label='username'
)
email = forms.EmailField(
error_messages={
'invalid': u"email invalid",
'required': u'required'},
label='email'
)
password1 = forms.CharField(
widget=forms.PasswordInput,
error_messages={
'required': u"required"
},
label='password1 '
)
password2 = forms.CharField(
widget=forms.PasswordInput,
error_messages={
'required': u"required"
},
label='password2'
)
def __init__(self, *args, **kwargs):
super(UserCreationForm, self).__init__(*args, **kwargs)
self.fields['username'].widget.attrs.update({'class': 'form-control'})
self.fields['email'].widget.attrs.update({'class': 'form-control'})
self.fields['password1'].widget.attrs.update({'class': 'form-control'})
self.fields['password2'].widget.attrs.update({'class': 'form-control'})
class Meta:
model = User
fields = ("username", "email")
def clean_username(self):
# Since User.username is unique, this check is redundant,
# but it sets a nicer error message than the ORM. See #13147.
username = self.cleaned_data["username"]
try:
User.objects.get(username=username)
except User.DoesNotExist:
return username
raise forms.ValidationError(
self.error_messages["duplicate_username"]
)
def clean_password2(self):
password1 = self.cleaned_data.get("password1")
password2 = self.cleaned_data.get("password2")
if password1 and password2 and password1 != password2:
raise forms.ValidationError(
self.error_messages["password_mismatch"]
)
password_validation.validate_password(password2)
return password2
def clean_email(self):
email = self.cleaned_data["email"]
try:
User.objects.get(email=email)
except User.DoesNotExist:
return email
raise forms.ValidationError(
self.error_messages["duplicate_email"]
)
def save(self, commit=True):
user = super(UserCreationForm, self).save(commit=False)
user.set_password(self.cleaned_data["password1"])
if commit:
user.save()
return user
I don't know why you are saving the object so many times. As documented here, when calling form.save() in a UserCreationForm instance, Django will create the user, set the password (which comes from the password1 field), save the instance in the database and return the user for you. So User.objects.create_user and user.save() will only save the object again.
Parhaps it's not the solution for your problem but have you tried just like this:
def user_register(request):
form = UserCreationForm()
if request.method == 'POST':
form = UserCreationForm(request.POST)
if form.is_valid():
user = form.save()
# if you want to authenticate your user or log any info, do it here
return redirect('home')
# I wouldn't use the else statement here, so if there are errors in the form you probably want the same template to be rendered, in order to show the form errors to your user.
return render(request, 'registration/register.html', {'form': form})
Thanks for everybody that helped me think this through. It seems, of course, the answer was much simpler than I thought. My new user_register view is:
from django.contrib.auth.forms import UserCreationForm
from django.shortcuts import render, redirect
def user_register(request):
form = UserCreationForm(request.POST)
if form.is_valid():
form.save()
return redirect('home')
else:
return render(request, 'registration/register.html', {'form': form})
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")
I'm designing this app and bumped into an unusual error which trying to fix but I just can't see where the error appears.I'm been trying to compare codes to see if I can find the error but both codes are identical just my code doesn't work
The tutorial came from here http://hackedexistence.com/project/django/video7-userauthentication-2.html
SyntaxError at /register/
('invalid syntax', ('C:\\djcode\\mysite\\drinker\\views.py', 23, 12, ' else:\n'))
Request Method: GET
Request URL: http://127.0.0.1:8000/register/
Django Version: 1.4.3
Exception Type: SyntaxError
Exception Value:
('invalid syntax', ('C:\\djcode\\mysite\\drinker\\views.py', 23, 12, ' else:\n'))
Exception Location: C:\Python26\Lib\site-packages\django\utils\importlib.py in import_module, line 35
Python Executable: C:\Python26\python.exe
Python Version: 2.6.0
My views.py
from django.http import HttpResponseRedirect
from django.contrib.auth.models import User
from django.contrib.decorators import login_required
from django.shortcuts import render_to_response
from django.template import RequestContext
from drinker.forms import RegistrationForm,LoginForm
from drinker.models import Drinker
from django.contrib.auth import authenicate ,login , logout
def DrinkerRegistration(request):
if request.user.is_authenticated():
return HttpResponseRedirect('/profile/')
if request.method == 'POST':
form = RegistrationForm(request.POST)
if form.is_valid():
user = User.objects.create_user(username=form.cleaned_data['username'], email = form.cleaned_data['email'] , password = form.cleaned_data['password'])
user.save()
drinker = Drinker(user=user , name=form.cleaned_data['name'] , birthday =form.cleaned_data['birthday'])
drinker.save()
return HttpResponseRedirect('/profile/')
else:
return render_to_response('register.html',{'form':form}, context_instance=RequestContext(request))
else:
form = RegistrationForm()
context = {'form':form}
return render_to_response('register.html',context,context_instance=RequestContext(request))
def LoginRequest(request):
if request.user.is_authenticated():
return HttpResponseRedirect('/profile/')
if request.method == 'POST':
form= LoginForm(request.POST)
if form.is_valid():
username = form.cleaned_data['username']
password = form.cleaned_data['password']
drinker = authenticate(username=username ,password=password)
if drinker is not None:
login(request,drinker)
return HttpResponseRedirect('/profile/')
else:
return render_to_response('login.html',{'form':form} , context_instance=RequestContext(request))
else:
return render_to_response('login.html',{'form': form}, context_instance=RequestContext(request))
else:
form= LoginForm()
context = {'form':form}
return render_to_response('login.html',context,context_instance=RequestContext(request))
def LogoutRequest(request):
logout(request)
return HttpResponseRedirect('/')
You are having 2 else: conditions. This is not valid syntax. Going to the link you provided you are making a indentation error. It should be like this. One else for inner if-else and other for outer if-else.
if request.method == 'POST':
form = RegistrationForm(request.POST)
if form.is_valid():
user = User.objects.create_user(username=form.cleaned_data['username'], email = form.cleaned_data['email'], password = form.cleaned_data['password'])
user.save()
drinker = Drinker(user=user, name=form.cleaned_data['name'], birthday=form.cleaned_data['birthday'])
drinker.save()
return HttpResponseRedirect('/profile/')
else:
return render_to_response('register.html', {'form': form}, context_instance=RequestContext(request))
else:
''' user is not submitting the form, show them a blank registration form '''
form = RegistrationForm()
context = {'form': form}
return render_to_response('register.html', context, context_instance=RequestContext(request))