I'm trying to create a registration form. Everything works fine until I try to raise a validation error in case email already exists. It says, 'User' object has no attribute 'ValidationError'
Here's what I did,
def register(request):
if request.method == 'POST':
form = RegistrationForm(request.POST)
if form.is_valid():
new_form = form.save(commit=False)
mail = form.cleaned_data['email']
if User.objects.filter(email=mail).exists():
raise new_form.ValidationError('Looks like email already exists')
else:
new_form.save()
username = request.POST.get('username')
password = request.POST.get('password1')
user = authenticate(username=username, password=password)
login(request, user)
return redirect(reverse('accounts:profile'))
else:
form = RegistrationForm()
How can we fix that?
When validating a form error, you should import validationError from django.forms and not django.core.exceptions
try :
from django.forms import ValidationError
try to add below method to your form
from django import forms
from .models import User
class RegistrationForm(forms.Form):
# ..............
# ..............
def clean(self):
mail = form.cleaned_data['email']
if User.objects.filter(email=mail).exists():
raise forms.ValidationError('Looks like email already exists')
return self.cleaned_data
change the code in views.py
if User.objects.filter(email=mail).exists():
raise new_form.ValidationError('Looks like email already exists')
else:
new_form.save()
to
new_form.save()
You should raise ValidationError like this:
raise ValidationError('Looks like email already exists')
Here is the full code:
def register(request):
if request.method == 'POST':
form = RegistrationForm(request.POST)
if form.is_valid():
new_form = form.save(commit=False)
mail = form.cleaned_data['email']
if User.objects.filter(email=mail).exists():
raise ValidationError('Looks like email already exists')
else:
new_form.save()
username = request.POST.get('username')
password = request.POST.get('password1')
user = authenticate(username=username, password=password)
login(request, user)
return redirect(reverse('accounts:profile'))
else:
form = RegistrationForm()
if User.objects.filter(email=mail).exists():
raise new_form.ValidationError('Looks like email already exists')
use "forms" instead of "new_form" the result should look like
if User.objects.filter(email=mail).exists():
raise forms.ValidationError('Looks like email already exists')
I typed as follows and it worked at django-2.0.7:
from django import forms
from django.contrib.auth import login
from django.contrib.auth.models import User
from django.shortcuts import render, redirect
class RegistrationForm(forms.ModelForm):
def clean_email(self):
email = self.cleaned_data['email']
if self.Meta.model.objects.filter(email=email).exists():
raise forms.ValidationError('Looks like email already exists')
return email
class Meta:
model = User
fields = ('username', 'password', 'email')
def register(request):
if request.method == 'POST':
form = RegistrationForm(request.POST)
if form.is_valid():
user = form.save(commit=False)
user.set_password(user.password)
user.save()
login(request, user)
return redirect('accounts:profile')
else:
form = RegistrationForm()
return render(request, 'register.html', {'form': form})
Related
I'm developing a site on Django, but I got an error ERR_TOO_MANY_REDIRECTS. I think that the matter is in the views.py file. Help figure it out.
P.S. already tried to delete cookie files, it didn't help(
from email import message
from wsgiref.util import request_uri
from django.shortcuts import redirect, render
from django.contrib.auth.models import User, auth
from django.contrib import messages
# Create your views here.
def reg(request):
if request.method == 'POST':
username = request.POST['username']
password = request.POST['password']
cpassword = request.POST['cpassword']
if password == cpassword:
if User.objects.filter(username=username):
messages.info(request, 'Username taken')
return redirect('registration')
else:
user = User.objects.create_user(username=username, password=password)
user.save()
return redirect('login')
else:
messages.info(request, 'Passwords not matching')
return redirect('registration')
return redirect('/')
else:
return render(request, 'registration.html')
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 logout(request):
auth.logout(request)
return redirect('/')
The problem is coming from your return redirect('/'). Redirect to one of the views written in your urls.py and your problem will be solved.
I am trying to have user validation in my django social media/blog app. I do not understand why this code does not work. The problem: No matter what name I type in the form it says the user does not exist even though the user does in fact exist. Any help would be amazing.
from django.shortcuts import render, redirect
from sign_in.forms import SignInForm
from django.contrib.auth.models import User
from django.contrib import messages
from django.contrib.auth.forms import forms
from django.http import HttpResponseRedirect
def sign_in(request):
if request.method == "POST":
form = SignInForm(request.POST)
if form.is_valid():
username = form.cleaned_data.get("username")
password = form.cleaned_data.get("password")
user = User.objects.filter(username=username, password=password)
if user.exists():
return HttpResponseRedirect("boom/")
else:
messages.error(request, f"User {user} does not exist.")
else:
form = SignInForm()
return render(request, "sign_in/sign_in.html", {"form": form})
this is not how Django authentication works.
https://docs.djangoproject.com/en/3.1/topics/auth/
use authenticate method
try this
from django.contrib.auth import login, authenticate
def sign_in(request):
if request.method == "POST":
form = SignInForm(request.POST)
if form.is_valid():
username = form.cleaned_data.get("username")
password = form.cleaned_data.get("password")
user = authenticate(username=username, password=password)
login(request, user)
if user.exists():
return HttpResponseRedirect("boom/")
else:
messages.error(request, f"User {user} does not exist.")
else:
form = SignInForm()
return render(request, "sign_in/sign_in.html", {"form": form})
I'd like to add Recaptcha to my login form. I'm following this repository but i'm having some problems: i added this to my views.py:
from django import forms
from captcha.fields import ReCaptchaField
class FormWithCaptcha(forms.Form):
captcha = ReCaptchaField()
But i don't really know where to go from here. I suppose i need to add something to my login.html page but i don't know what. Can anyone give me some help? Note that i already added my public and private keys to my settings.py file.
This is the whole views.py:
from django.shortcuts import render, redirect
from django.http import HttpResponse
from .models import Tutorial
from django.contrib.auth.forms import AuthenticationForm
from django.contrib.auth import login, logout, authenticate
from django.contrib import messages
from .forms import NewUserForm
from django import forms
from captcha.fields import ReCaptchaField
class FormWithCaptcha(forms.Form):
captcha = ReCaptchaField()
def homepage(request):
return render(request=request,
template_name="main/home.html",
context={"tutorials": Tutorial.objects.all})
def register(request):
if request.method == "POST":
form = NewUserForm(request.POST)
if form.is_valid():
user = form.save()
username = form.cleaned_data.get('username')
messages.success(request, f"New Account Created: {username}")
login(request, user)
messages.info(request, f"You are now logged in as {username}")
return redirect("main:homepage")
else:
for msg in form.error_messages:
messages.error(request, f"{msg}: {form.error_messages[msg]}")
form = NewUserForm
return render(request,
"main/register.html",
context={"form":form})
def logout_request(request):
logout(request)
messages.info(request, "Logged out successfully!")
return redirect("main:homepage")
def login_request(request):
if request.method == "POST":
form = AuthenticationForm(request, data=request.POST)
if form.is_valid():
username = form.cleaned_data.get('username')
password = form.cleaned_data.get('password')
user = authenticate(username=username, password=password)
if user is not None:
login(request, user)
messages.info(request, f"You are now logged in as {username}")
return redirect("main:homepage")
else:
messages.error(request, "Invalid username or password")
else:
messages.error(request, "Invalid username or password")
form = AuthenticationForm()
return render(request,
"main/login.html",
{"form":form})
You can achieve your goal without external libs by subclassing LoginForm from django.contrib.auth
Please see this answer for code examples and a more detailed explanation. Using context processors you can also add the recaptcha public key into login.html template.
You should post your views.pyso I could help you better, but using common Django sense, you should render the login.html file with FormWithCaptcha as a context variable, named recaptcha, for example and then in your login file call it like {{recaptcha}} wherever you need it. But again, post your views file if your issue is not yet fixed.
def login_request(request):
if request.method == "POST":
form = AuthenticationForm(request, data=request.POST)
if form.is_valid():
username = form.cleaned_data.get('username')
password = form.cleaned_data.get('password')
user = authenticate(username=username, password=password)
if user is not None:
login(request, user)
messages.info(request, f"You are now logged in as {username}")
return redirect("main:homepage")
else:
messages.error(request, "Invalid username or password")
else:
messages.error(request, "Invalid username or password")
form = AuthenticationForm()
recaptcha = FormWithCaptcha()
return render(request,
"main/login.html",
{"form":form, "recaptcha": recaptcha})
Here's my forms.py,
class RegistrationForm(UserCreationForm):
class Meta:
model = User
fields = [ 'username', 'first_name', 'password1', 'password2']
def save(self, commit=True):
user = super(RegistrationForm, self).save(commit=False)
user.first_name = self.cleaned_data['first_name']
if commit:
user.save()
return user
In views.py,
def register(request):
if request.method == 'POST':
form = RegistrationForm(request.POST)
if form.is_valid():
form.save()
username = request.POST.get('username')
password = request.POST.get('password1')
user = authenticate(username=username, password=password)
login(request, user)
return redirect(reverse('accounts:profile'))
else:
form = RegistrationForm()
return render(request, 'accounts/reg_form.html', {'form': form})
Right now if i'm using the same username it's raising an error which says "The view accounts.views.register didn't return an HttpResponse object. It returned None instead." How can I fix this issue?
Thank You :)
Django form by default does this for you.
You don't need specific for this.
Beacuse, default User Model provided by django doesn't take duplicate username.
May be some indentation problem
def register(request):
if request.method == 'POST':
form = RegistrationForm(request.POST)
if form.is_valid():
form.save()
. . . .
else:
form = RegistrationForm()
return render(request, 'accounts/reg_form.html', {'form': form})
#^^^^^Indentation here take return statement outside else
I initially used to login using email and password but now want to change it in such a way that we can login using either mobile no or email address and password.I am not able to understand what parts to change in my code as I do not want to delete already existing user and data.
forms.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 = ['first_name', 'last_name', 'email', 'password']
views.py
class UserFormView(View):
form_class = UserForm
template_name = 'main/registration_form.html'
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
email = form.cleaned_data['email']
password = form.cleaned_data['password']
user.username = email
user.set_password(password)
user.save()
# return user objects if credentials are correct
user = authenticate(username=email, password=password)
if user is not None:
if user.is_active:
login(request, user)
# request.user.username display their username
return redirect('main:register2')
return render(request, self.template_name, {'form': form})
class LoginForm(View):
form_class = UserForm
template_name = 'main/login_form.html'
def get(self, request):
form = self.form_class(None)
if error:
return render(request, self.template_name, {'form': form},
{'error': error})
else:
return render(request, self.template_name, {'form': form})
def post(self, request):
email = request.POST.get('email', '')
password = request.POST.get('password', '')
user = auth.authenticate(username=email, password=password)
if user is not None and user.is_active:
# Correct password, and the user is marked "active"
auth.login(request, user)
# Redirect to a success page.
return HttpResponseRedirect("/main/home/")
else:
# Show an error page
error = True
return HttpResponseRedirect("/main/", {'error': error})
Please answer considering the fact that I am new to Django. Thanks in advance :)
In the post method of your view, identify what has the user given you. If it's an email, feed the Django's authenticate() method with the email. If not, then assume it's a phone number (you may also run additional validations in there) and use this in the authentication procedure.
Another approach would be to create a custom authenticate() method, which would look like this:
from django.contrib.auth.backends import ModelBackend
class MobilePhoneOrEmailModelBackend(ModelBackend):
def authenticate(self, username=None, password=None):
# the username could be either one of the two
if '#' in username:
kwargs = {'email': username}
else:
kwargs = {'mobile_phone': username}
try:
user = User.objects.get(**kwargs)
if user.check_password(password):
return user
except User.DoesNotExist:
return None
def get_user(self, username):
try:
return User.objects.get(pk=username)
except User.DoesNotExist:
return None
Let me know if this worked out well for you.
Credits to user user3282276 in this thread as well: Log in user using either email address or username in Django