Django Authentication and Login Issue with Class Based Views - django

I am trying to achieve two different views: one for registration purpose and one for login purpose.
Now, the registration process works perfectly but the authentication process does not.
Here's the code:
in forms.py the first form called UserForm is used to sign up users, the second form called LoginForm is used to log in users.
from django.contrib.auth.models import User
from django import forms
class UserForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput)
class Meta:
model = User
fields = ['first_name', 'last_name', 'username', 'email', 'password']
class LoginForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput)
class Meta:
model = User
fields = ['username', 'email', 'password']
in views.py
from django.shortcuts import render, get_object_or_404, redirect
from .models import Step, Cycle, Program, MotorSetting, GeneralSetting
from django.views import generic
from django.views.generic.edit import CreateView, UpdateView, DeleteView
from django.core.urlresolvers import reverse_lazy
from django.contrib.auth import authenticate, login
from django.views.generic import View
from .forms import UserForm
from .forms import LoginForm
class UserFormView(View):
form_class = UserForm
template_name = 'programs/registration_form.html'
# display blank form
def get(self, request):
form = self.form_class(None)
return render(request, self.template_name, {'form': form})
#process form data
def post(self, request):
form = self.form_class(request.POST)
if form.is_valid():
#storing the data but NOT SAVING them to db yet
user = form.save(commit=False)
#cleaning and normalizing data
username = form.cleaned_data['username']
password = form.cleaned_data['password']
user.set_password(password)
#saving to db
user.save()
#if credentials are correct, this returns a user object
user = authenticate(username=username, password=password)
if user is not None:
if user.is_active:
login(request, user)
return redirect('programs:index')
return render(request, self.template_name, {'form': form})
class LoginFormView(View):
form_class = LoginForm
template_name = 'programs/login_form.html'
# display blank form
def get(self, request):
form = self.form_class(None)
return render(request, self.template_name, {'form': form})
#process form data
def post(self, request):
form = self.form_class(request.POST)
if form.is_valid():
#storing the data but NOT SAVING them to db yet
user = form.save(commit=False)
#if credentials are correct, this returns a user object
user = authenticate(username=username, password=password)
if user is not None:
if user.is_active:
login(request, user)
return redirect('programs:index')
return render(request, self.template_name, {'form': form})
in app/urls.py
from django.conf.urls import include, url
from . import views
app_name = 'programs'
urlpatterns = [
#register page
url(r'^register/$', views.UserFormView.as_view(), name='register'),
#login page
url(r'^login/$', views.LoginFormView.as_view(), name='login'),
]
The registration process goes smoothly, the authentication/login does not. When I fill in the form to login and press send, nothing happens apart from the form getting blank again.
Is there any error I'm not seeing in the code?
Many thanks!

Related

How to get individual users data after login in django?

iam new to django.Can anyone send me the code of signup and login page to get particular details of the username without using django.contrib.auth.models import User.
(i.e if we login with some usename then it should only give details of that username not remaining).
Find view you want manipulate user in, declare user like current_user = request.user. I will provide you my login and register views below. In examples shown below I had from django.contrib.auth.models import User, but you can modify it as shown above.
Register:
def registerPage(request):
if request.user.is_authenticated:
return redirect('todoapp:home')
else:
form = CreateUserForm()
if request.method == 'POST':
form = CreateUserForm(request.POST)
email = request.POST.get('email')
if form.is_valid():
if check_does_email_already_exist(email):
form.save()
messages.success(request, "User is registered sucessfully")
return redirect('todoapp:login')
else:
messages.warning(
request, "User with same email already exist")
else:
messages.warning(
request, "That username already exist or your password is too short")
context = {
'form': form,
}
return render(request, 'register.html', context)
Login:
def loginPage(request):
if request.user.is_authenticated:
return redirect('todoapp:home')
else:
if request.method == 'POST':
username = request.POST.get('uname')
password = request.POST.get('passwd')
user = authenticate(username=username, password=password)
if user is not None:
login(request, user)
return redirect('todoapp:home')
else:
messages.warning(
request, "Your password or username isn't valid")
return redirect('todoapp:login')
else:
pass
return render(request, 'login.html')
These are my imports:
from django.shortcuts import render, redirect
from django.urls import reverse
from django.utils import timezone
from django.http import HttpResponseRedirect
from django.urls import reverse
from django.shortcuts import get_object_or_404
from django.contrib.auth import authenticate, login, logout
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from .forms import CreateUserForm
And this is my forms.py:
from django.contrib.auth.forms import UserCreationForm
from django import forms
from django.contrib.auth.models import User
from django.forms import fields
class CreateUserForm(UserCreationForm):
class Meta:
model = User
fields = [
'username',
'email',
'password1',
'password2',
]
I hope my answer will help you.

django userform not showing in HTML page

I am new to django . here I want to register user and I have a problem , the user form doesnt show in registration html page
here is my code:
views.py :
enter code here
from django.views.generic.edit import CreateView, UpdateView, DeleteView
from django.core.urlresolvers import reverse_lazy
from django.shortcuts import render, redirect
from django.contrib.auth import authenticate, login
from django.views import generic
from django.views.generic import View
from .forms import UserForm
from .models import Album
class UserFormView(View):
form_class = UserForm
template_name = 'music/registration_form.html'
# display blank form
def get(self, request):
form = self.form_class(None)
return render(request, self.template_name, {'form': form})
def post(self, request):
form = self.form_class(request.POST)
if form.is_valid():
user = form.save(commit=False)
# cleaned (Normalized) data
username = form.cleaned_data['username']
password = form.cleaned_data['password']
user.set_password(password)
user.save()
# return user objects if info r correct
user = authenticate(username=username, password=password)
if user is not None:
if user.is_active:
login(request, user)
return redirect('music:index')
return render(request, self.template_name, {'form': form})
form.py :
from django.contrib.auth.models import User
from django import forms
class UserForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput)
class Meta:
model = User
fields = ['username', 'email', 'password']
I think there is nothing wrong with url.py as long as the page pops up, I dunno where I'm mistaken

django too many redirects after login

I am running: Django==2.0.6 / python==3.6.5 / django-allauth==0.36.0
I have not touched this project in several weeks. I upgraded a number of packages before starting this round of development.
I can currently create a new user account and verify the email address used as the username. The user model is "extended" in that I use the email address for the username and have a "Profile" class to hold additional interesting fields.
I was once able to create a new account, verify the email address and be taken to a form to fill out that additional interesting info. Now, after email verification there is a noticable pause and then I am told that I have ben redirected too many times.
My urls.py looks like:
from django.urls import path, re_path
from .views import index
from .views import profile
urlpatterns = [
re_path(r'^', index, name='index'),
path('Profile/<uuid:account_number>/edit', profile.Update.as_view(), name="profile-update"),
path('Profile/<uuid:account_number>/delete', profile.Delete.as_view(), name="profile-delete"),
path('Profile/create', profile.Create.as_view(), name="profile-create"),
]
The Profile CBV is:
import django.contrib.messages as messages
from allauth.account.decorators import verified_email_required
from django.contrib.auth.models import User
from django.shortcuts import get_object_or_404
from django.shortcuts import redirect
from django.shortcuts import render
from django.utils.decorators import method_decorator
from django.views.generic import CreateView, UpdateView, DeleteView
from Members.forms.profile import ProfileForm
from Members.models.profile import Profile
import datetime
#method_decorator(verified_email_required, name='dispatch')
class Create(CreateView):
model = Profile
template_name = 'Members/profile.html'
form_class = ProfileForm
success_url = 'Members/index.html'
def get(self, request, *args, **kwargs):
return render(request, self.template_name, {
'profileForm': self.form_class(),
'profileState': "create"
})
def post(self, request, *args, **kwargs):
form = self.form_class(request.POST)
if form.is_valid():
profile = form.save(commit=False)
profile.user = self.request.user
profile.save()
my_render = render(request, self.success_url, {
'profile': profile,
'profileState': "display"
})
else:
#
# form has issues. send it back to the create form to fix.
my_render = render(request, self.template_name, {
'profileForm': form,
'profileState': "editForCreate"
})
return my_render
#method_decorator(verified_email_required, name='dispatch')
class Update(UpdateView):
pk_url_kwarg = "account_number"
model = Profile
template_name = 'Members/profile.html'
form_class = ProfileForm
success_url = 'Members/index.html'
def get(self, request, *args, **kwargs):
profile = Profile.objects.get(account_number=self.kwargs[self.pk_url_kwarg])
form = ProfileForm(instance=profile)
return render(request, self.template_name, {
'profileForm': form,
'profileState': "edit"
})
def post(self, request, *args, **kwargs):
profile = Profile.objects.get(account_number=self.kwargs[self.pk_url_kwarg])
form = ProfileForm(request.POST, instance=profile)
if form.is_valid():
profile = form.save(commit=False)
profile.user = request.user
profile.dateModified = datetime.datetime.now()
profile.save()
my_render = render(request, 'Members/index.html', {
'profile': profile
})
else:
#
# form has issues. send it back to the create form to fix.
my_render = render(request, self.template_name, {
'profileForm': form,
'profileState': "editForUpdate"
})
return my_render
#method_decorator(verified_email_required, name='dispatch')
class Delete(DeleteView):
pk_url_kwarg = "account_number"
model = Profile
# form_class = ProfileForm
success_url = "account/login.html"
def get(self, request, *args, **kwargs):
try:
#
# I can't believe django does not honor on_delete cascade.
# Have to roll your own. Tsk
owner = self.request.user
profile = get_object_or_404(Profile, account_number=self.kwargs[self.pk_url_kwarg])
user_pk = profile.user.pk
profile.delete()
get_object_or_404(User, pk=user_pk).delete()
messages.success(request, "The user is deleted")
except User.DoesNotExist:
messages.error(request, "User does not exist")
# except IntegrityError:
# messages.error(request, "DB IntegrityError")
return redirect("accounts/login/")
How do you go about debugging this? Ive tried setting breakpoints in PyCharm but they are ignored or ar in the wrong places.
in your urls.py you need to add $ in order to close your regular expression
urlpatterns = [
re_path(r'^$', index, name='index'),
]

Login using Class based view didn't work as expected while trying to login a user using email

my views.py:
from django.http import HttpResponse
from django.shortcuts import render, render_to_response
from django.contrib.auth import login, authenticate
from django.contrib.auth.models import User
from django.shortcuts import render
from django.views.generic import View
from .forms import LoginForm, RegistrationForm
class Login(View):
form_class = LoginForm
initial = {'key': 'value'}
template_name = 'web/login.html'
def get(self, request):
form = self.form_class(initial=self.initial)
return render(request, self.template_name, {'form': form})
def post(self, request):
if request.method == 'POST':
form = self.form_class(initial=self.initial)
if form.is_valid():
email=form.cleaned_data['email']
password=form.cleaned_data['password']
auser = User.objects.get(email=email)
username = auser.username
buser = authenticate(username, password)
if buser:
if buser.is_active:
login(request, buser)
return HttpResponse('Good to Go...')
else:
return HttpResponse('your account is disabled...')
else:
print "Invalid login details: {0}, {1}".format(email, password)
HttpResponse('invalid login details...')
else:
return HttpResponse('Form is not valid!')
else:
form = self.form_class()
Here above I'm trying to login a user using email as unique field in class based views. But It raises 'Form is not valid!' as I specified in my views. I don't know what's going wrong with it exactly. Please Help me how to fix it?
Thanks in Advance
You need to change the post method of this class:
def post(self, request):
if request.method == 'POST':
form = self.form_class(data=self.request.POST)
if form.is_valid():
.....

How to automatically login a user after registration in django

This is what I am currently using for registration:
def register(request):
if request.method == 'POST':
form = UserCreationForm(request.POST)
if form.is_valid():
new_user = form.save()
messages.info(request, "Thanks for registering. Please login to continue.")
return HttpResponseRedirect("/dashboard/")
else:
form = UserCreationForm()
return render_to_response("accounts/register.html", {
'form': form,
}, context_instance=RequestContext(request))
Is it possible not to require the user to login manually after creating an account, but rather simply to log them in automatically? Thanks.
edit: I had tried the login() function without success. I believe the problem is that AUTHENTICATION_BACKENDS was not set.
Using the authenticate() and login() functions:
from django.contrib.auth import authenticate, login
def register(request):
if request.method == 'POST':
form = UserCreationForm(request.POST)
if form.is_valid():
new_user = form.save()
messages.info(request, "Thanks for registering. You are now logged in.")
new_user = authenticate(username=form.cleaned_data['username'],
password=form.cleaned_data['password1'],
)
login(request, new_user)
return HttpResponseRedirect("/dashboard/")
for class based views here was the code that worked for me (originally Django 1.7, updated for 2.1)
from django.contrib.auth import authenticate, login
from django.contrib.auth.forms import UserCreationForm
from django.http import HttpResponseRedirect
from django.views.generic import FormView
class SignUp(FormView):
template_name = 'signup.html'
form_class = UserCreateForm
success_url='/account'
def form_valid(self, form):
#save the new user first
form.save()
#get the username and password
username = self.request.POST['username']
password = self.request.POST['password1']
#authenticate user then login
user = authenticate(username=username, password=password)
login(self.request, user)
return HttpResponseRedirect(self.get_success_url)
The accepted answer doesn't seem to work with Django 4.0 (for me, at least), or alternatively it doesn't work with custom user models that have custom user managers.
This is how I solved the issue (adapted from https://stackoverflow.com/a/31491942 and https://stackoverflow.com/a/68515276):
from django.views.generic import CreateView
from django.urls import reverse_lazy
from django.contrib.auth import authenticate, login
from your.custom.user.models import User
class SignUpView(CreateView):
model = User
fields = ["username", "email", "password"]
success_url = reverse_lazy("success_url_name") # change this with your own URL
def form_valid(self, form):
# create the user object
user = form.save(commit=False)
# set password manually
# as otherwise the User will be saved with unhashed password
user.set_password(form.cleaned_data.get("password"))
# save your User object to the database
user.save()
# get email and password
email = form.cleaned_data.get("email")
password = form.cleaned_data.get("password")
# authenticate your user with unhashed password, because `authenticate` hashes it again
authenticated_user = authenticate(email=email, password=password)
# log in
login(self.request, authenticated_user)
return redirect(self.success_url)
You need to manually set the password, so that the database contains the hashed password. Without that, your unhashed password will be saved to the database, which will prevent you from logging in afterwards, as authentication involves hashing the password and checking that against the database.
using only "login()" in django-4.0.3
from django.contrib.auth import login
def registration(request):
if request.POST:
form = UserCreationForm(request.POST)
if form.is_valid():
user = form.save()
login(request, user)
username = form.cleaned_data.get('username')
messages.success(request, f'Account created for {username}')
return redirect('home')
You can subclass Django's UserCreationForm and override it's save method to log them in when commit=True.
forms.py
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth import login
class CustomUserCreationForm(UserCreationForm):
"""
A ModelForm for creating a User and logging
them in after commiting a save of the form.
"""
def __init__(self, request, *args, **kwargs):
super().__init__(*args, **kwargs)
self.request = request
class Meta(UserCreationForm.Meta):
pass
def save(self, commit=True):
user = super().save(commit=commit)
if commit:
auth_user = authenticate(
username=self.cleaned_data['username'],
password=self.cleaned_data['password1']
)
login(self.request, auth_user)
return user
You just need to make sure you pass in a request object when you instantiate the form. You can do that by overriding the view's get_form_kwargs method.
views.py
def get_form_kwargs(self):
form_kwargs = super().get_form_kwargs()
form_kwargs['request'] = self.request
return form_kwargs
Or, make sure when you instantiate a form_class you do CustomUserCreationForm(data=request.POST, request=self.request).
The Django auth.login function makes it easy to log in a user, given a request and User instance.
Note: remember to add the necessary imports for the following examples.
from django.contrib.auth import login
from django.shortcuts import render, redirect
In a function-based view, the following should work.
if form.is_valid():
user = form.save()
login(request, user)
return redirect("desired-url")
For a class-based view (such as CreateView or FormView), you can override the form_valid method:
def form_valid(self, form):
"""If the form is valid, save the associated model and log the user in."""
user = form.save()
login(self.request, user)
return redirect(self.success_url)