I have an form that allows a user to create a user account.The problem is , whenever a user submit a username that already been taken through the system . The form doesn't raise an error but it does raise an error when a field is missing. Can someone kindly help me
def Registration(request):
form = UserRegistration()
if request.method =='POST':
form = UserRegistration(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.is_active = True
user.save()
return render(request,'choose.html',{'form':form})
return render(request, 'register.html', {'form': form},)
My forms.py
class UserRegistration(forms.Form):
username = forms.CharField()
email = forms.EmailField(error_messages={'required':'Error Missing Field , Please Fill this Field'})
password = forms.CharField(
widget=forms.PasswordInput(render_value=False)
)
def clean(self):
cleaned_data = super(UserRegistration, self).clean()
username = cleaned_data.get("username")
password = cleaned_data.get("password")
user = User.objects.filter(username=username)
if user :
raise forms.ValidationError(
"That user is already taken , please select another ")
return cleaned_data
My template
<form method ="POST">
{% csrf_token %}
<span id="error">{{form.username.errors}}</span>
<span id="error2">{{form.email.errors}}</span>
<span id="error3">{{form.password.errors}}</span>
{{form.username}}
{{form.email}}
{{form.password}}
<input type = "submit" value= "save" id="box2"/>
</form>
You should use the exists[0] method:
user = User.objects.filter(username=username)
if user.exists():
raise forms.ValidationError("That user is already taken")
Edit:
Try using the clean_username method:
class UserRegistration(forms.Form):
....
def clean_username(self):
username = self.cleaned_data['username']
if User.objects.filter(username=username).exists():
raise forms.ValidationError("That user is already taken")
return username
You could add a Test to make sure it works:
from django.test import TestCase
class TestUniqueUsername(TestCase):
def test_unique_username(self):
User.objects.create(username='test', password='test', email='test#django.com')
form = UserCreationForm(data={'username': 'test'})
self.assertFalse(form.is_valid())
[0] https://docs.djangoproject.com/en/dev/ref/models/querysets/#django.db.models.query.QuerySet.exists
Try this code
class UserRegistration(forms.Form):
username = forms.CharField()
email = forms.EmailField(error_messages={'required':'Error Missing Field , Please Fill this Field'})
password = forms.CharField(
widget=forms.PasswordInput(render_value=False)
)
def clean_username(self):
cleaned_data = self.cleaned_data
username = cleaned_data.get("username")
user = User.objects.filter(username=username)
if user.count() > 0:
raise forms.ValidationError("That user is already taken , please select another ")
return username
This will do the trick.
Related
I have issue is that in template, I automatically get access of username of Superuser (if that is logged-in) but not username of user based on Buyer (Model). User is getting registered and also can login (I can see it in database). But in template I am unable to get username of user other than superuser. I don't what i am missing here. So i am putting all code of view.py here. Also after user logging he sees bookrepo:home and i am using user logic in header.html (bookrepo:home extends header.html)
I have model named Buyer in models.py file. And based on this model, two modelForm has made.
This is code of model.py
class Buyer(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
user = models.OneToOneField(User, on_delete=models.DO_NOTHING)
# additional attributes
contact = models.CharField('Contact #', max_length=16, unique=True, validators=[
RegexValidator(
regex=r'^\+?1?\d{9,15}$',
message="Phone number (Up to 15 digits) must be entered in the format: '+923001234567'."
),
], )
devices = models.CharField('Devices', unique=False, max_length=115, blank=True)
picture = models.ImageField(upload_to=profile_pic_path, null=True,blank=True)
def __str__(self):
return "{} {}".format(self.user.first_name, self.user.last_name)
class Meta:
get_latest_by = '-user.date_joined'
This is code of modelForms
class RegistrationForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput())
confirm_password = forms.CharField(widget=forms.PasswordInput())
class Meta():
model = User
fields = ('username',
'email',
'password')
def clean(self):
cleaned_data = super(RegistrationForm, self).clean()
password = cleaned_data.get("password")
confirm_password = cleaned_data.get("confirm_password")
if password != confirm_password:
raise forms.ValidationError(
"Password and Confirm Password does not match"
)
class RegistrationFormPlus(forms.ModelForm):
class Meta():
model = Buyer
fields = ('contact',)
This is code of header.html (NOT the home.html)
{% if user.is_authenticated %}
<a class="nav-link" href="{% url 'bookrepo:logout' %}">Logout</a>
<h2>Welcome {{ user.username }}!</h2>
{% else %}
<a class="nav-link" href="{% url 'bookrepo:user_login' %}">Login</a>
{% endif %}
This is code of views.py
def home(req):
bookz = Book.objects.order_by('title')
var = {'books': bookz, 'range': 10}
return render(req, 'bookrepo/home.html', context=var)
def registration(request):
registered = False
if request.method == 'POST':
reg_form = RegistrationForm(data=request.POST)
reg_form_plus = RegistrationFormPlus(data=request.POST)
if reg_form.is_valid() and reg_form_plus.is_valid():
user = reg_form.save()
user.set_password(user.password)
user.save()
user_plus = reg_form_plus.save(commit=False)
user_plus.user = user
user_plus.save()
registered = True
else:
print(reg_form.errors, reg_form_plus.errors)
print("else 2 chala")
else:
reg_form = RegistrationForm()
reg_form_plus = RegistrationFormPlus()
return render(request, 'bookrepo/signup.html',
{'reg_form': reg_form,
'reg_form_plus': reg_form_plus,
'registered': registered
})
#login_required
def special(request):
return HttpResponse("You are logged in. Nice!")
#login_required
def user_logout(request):
logout(request)
return HttpResponseRedirect(reverse('bookrepo:home'))
def user_login(request):
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
user = authenticate(username=username, password=password)
if user:
return HttpResponseRedirect(reverse('bookrepo:home'))
else:
print("Someone tried to login and failed.")
print("They used username: {} and password: {}".format(username, password))
return HttpResponse("Invalid login details supplied.")
else:
return render(request, 'bookrepo/login.html', {})
You should use {{ buyer.user.username }} in your template to show the username of a user.
You are trying to extend your django user framework with a One To One Field . new extended Django Model used to store the extra information that relates to the User Model. {{user.username}} gives the username from session.
use this code to authenticate users don't forgot to import
from django.contrib.auth.models import User,auth
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('index')
else:
messages.info(request,'invalid user')
return redirect('login')
else:
return render(request,"login.html")
I'm setting up a custom-user registration form to create an account on my Django project. I feel I'm missing something very simple that keeps me from registering for some reason.
My registration form demands 4 fields to be filled before a new user can register. Of these 4 fields, two are just a confirmation of the email address.
Here is a copy of my form.py:
class UserRegisterForm(forms.ModelForm):
username = forms.CharField(label='Username')
email = forms.EmailField(label='Email Address')
email2 = forms.EmailField(label='Confirm Email')
password = forms.CharField(widget=forms.PasswordInput)
class Meta:
model = CustomUser
fields = ['username', 'email', 'email2', 'password']
def clean_email(self):
email = self.cleaned_data.get('email')
email2 = self.cleaned_data.get('email2')
if email != email2:
raise forms.ValidationError("Emails do not match")
And here is a copy of my view.py:
def register_view(request):
next = request.GET.get('next')
form = UserRegisterForm(request.POST or None)
if form.is_valid():
user = form.save(commit=False)
password = form.cleaned_data.get('password')
user.set_password(password)
user.save()
new_user = authenticate(username=user.username, password=password)
login(request, new_user)
if next:
return redirect(next)
return redirect('/home/')
context = {'form':form, "title":"register"}
return render(request, "register.html", context)
Here is my html file:
<h2><center><font color="white">Register Here:</font></center></h2>
<form method="POST"><center>
{% csrf_token %}
{{form}}
<input type="submit" />
</center></form>
Whenever I try to register as a new user, my form validation error is raised as is says that my two emails do not match (I copy-paste them to make sure they are identical).
I feel I'm missing something that is right under my nose...
Cheers to all of you and thank you very much.
try this
def register_view(request):
next = request.GET.get('next')
form = UserRegisterForm(request.POST or None)
if form.is_valid():
email = form.cleaned_data.get('email')
email1 = form.cleaned_data.get('email1')
if email1 == email
user = form.save(commit=False)
password = form.cleaned_data.get('password')
user.set_password(password)
user.save()
new_user = authenticate(username=user.username, password=password)
login(request, new_user)
if next:
return redirect(next)
else:
….
def clean(self):
cleaned_data = super(UserRegisterForm, self).clean()
email = cleaned_data.get('email')
email2 = cleaned_data.get('email2')
if email != email2:
self.add_error("email", "Emails do not match")
The problem is that in clean_email method you have email2 to be always None. To compare two or more fields use clean method
I have a registration that let users register and i'm having difficulty fixing it.
The problem is when a user submits a single field instead of the whole form for example an email . I get this error
KeyError at /register/
password
Request Method: POST
Request URL: http://127.0.0.1:8000/register/
File "C:\Python26\Lib\site-packages\django\forms\forms.py" in _get_errors
115. self.full_clean()
File "C:\Python26\Lib\site-packages\django\forms\forms.py" in full_clean
271. self._clean_form()
File "C:\Python26\Lib\site-packages\django\forms\forms.py" in _clean_form
299. self.cleaned_data = self.clean()
File "C:\o\17\mysite\pet\forms.py" in clean
31. if self.cleaned_data['password'] != self.cleaned_data['password1']:
Exception Type: KeyError at /register/
Exception Value: password
I tried to fix this solution using if . If user has a submitted a username or any other required field , process the form otherwise redisplay the original form.
but I still get the same error.
This is my edited views.py (at the bottom of the page is my original RegistrationForm)
def PetRegistration(request):
if request.user.is_authenticated():
return HttpResponseRedirect(reverse('world:HappyLand'))
if request.method =='POST':
form = UserRegistration(request.POST)
if form.is_valid():
username = form.cleaned_data['username']
if username:
email=form.cleaned_data['email']
if email:
password=form.cleaned_data['password']
if password:
user = User.objects.create_user(
username=form.cleaned_data['username'],
email=form.cleaned_data['email'],
password=form.cleaned_data['password']
)
user.is_active = True
user.first_name = form.cleaned_data['name']
user.save()
person = authenticate(
username=form.cleaned_data['username'],
password=form.cleaned_data['password']
)
Person.objects.create(user_id=user.id,
name=form.cleaned_data['name'],birthday=form.cleaned_data['birthday'])
login(request, person)
return HttpResponseRedirect(reverse('world:HappyLand'))
return render(request, 'register.html', {'form': UserRegistration()})
How can I fix this error and also how could I display an error message on the other fields that the user didn't fill out like "Error Missing Field , Please Fill this Field".
def PetRegistration(request):
if request.user.is_authenticated():
return HttpResponseRedirect(reverse('world:HappyLand'))
if request.method =='POST':
form = UserRegistration(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.is_active = True
user.first_name = form.cleaned_data['name']
user.save()
person = authenticate(
username=form.cleaned_data['username'],
password=form.cleaned_data['password']
)
Person.objects.create(user_id=user.id,
name=form.cleaned_data['name'],birthday=form.cleaned_data['birthday'])
login(request, person)
return HttpResponseRedirect(reverse('world:HappyLand'))
return render(request, 'register.html', {'form': UserRegistration()})
My forms.py
class UserRegistration(forms.Form):
username = forms.CharField()
name = forms.CharField()
email = forms.EmailField()
birthday = forms.DateField(widget=extras.SelectDateWidget(years=range(1950, 2012)))
password = forms.CharField(
widget=forms.PasswordInput(render_value=False)
)
password1 = forms.CharField(
label=(u'Verify Password'),
widget = forms.PasswordInput(render_value=False)
)
def clean_username(self):
username = self.cleaned_data['username']
try:
User.objects.get(username=username)
except User.DoesNotExist:
return username
raise forms.ValidationError(
"That user is already taken , please select another ")
def clean(self):
if self.cleaned_data['password'] != self.cleaned_data['password1']:
raise forms.ValidationError("The password does not match ")
return self.cleaned_data
My models.py
class Person(models.Model):
user = models.ForeignKey(User)
name = models.CharField(max_length=100, blank=True)
birthday = models.DateField(blank=True,null=True)
def __unicode__(self):
return self.name
Problem is with your clean(). In clean(), you are trying to access field password on form's cleaned_data. password will only be available on cleaned_data if the user has filled this field. So, you must check that password is there in cleaned_data before trying to access it.
Changing your clean():
def clean(self):
if 'password' in self.cleaned_data and 'password1' in self.cleaned_data and self.cleaned_data['password'] != self.cleaned_data['password1']:
raise forms.ValidationError("The password does not match ")
return self.cleaned_data
You can provide a keyword argument error_messages on form field for showing error message like "Error Missing Field , Please Fill this Field".
class SomeForm(forms.Form):
name = forms.CharField(error_messages={'required':'Error Missing Field , Please Fill this Field'})
There is a bug in your view.
is_valid() populates errors on the form but this same form instance must be sent to the template so that you can access the errors on the form's fields.
But in your view, you have only one call to render() which gets called even in case of an invalid form on a post request. And in this render(), you are creating a new instance of form. So, this new form which you are sending to template will not have any errors.
So, making slight modification to your view:
def PetRegistration(request):
if request.user.is_authenticated():
return HttpResponseRedirect(reverse('world:HappyLand'))
form = UserRegistration() #This will be used in GET request
if request.method =='POST':
form = UserRegistration(request.POST) #This will be used in POST request
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.is_active = True
user.first_name = form.cleaned_data['name']
user.save()
person = authenticate(
username=form.cleaned_data['username'],
password=form.cleaned_data['password']
)
Person.objects.create(user_id=user.id,
name=form.cleaned_data['name'],birthday=form.cleaned_data['birthday'])
login(request, person)
return HttpResponseRedirect(reverse('world:HappyLand'))
return render(request, 'register.html', {'form': form})
Notice in your view, I have added form=UserRegistration() before checking if its POST request, and have added the comment at two places where we are instantiating UserRegistration. And then in render(), you should send this form.
Then your {{form.username.errors}} will work.
I just modified your forms.py
class UserRegistration(forms.Form):
username = forms.CharField()
name = forms.CharField()
email = forms.EmailField()
birthday = forms.DateField(widget=extras.SelectDateWidget(years=range(1950, 2012)))
password = forms.CharField(
widget=forms.PasswordInput(render_value=False)
)
password1 = forms.CharField(
label=(u'Verify Password'),
widget = forms.PasswordInput(render_value=False)
)
def clean(self):
cleaned_data = super(UserRegistration, self).clean()
username = cleaned_data.get("username")
password = cleaned_data.get("password")
password1 = cleaned_data.get("password1")
#check if username exist
user = User.objects.filter(username=username)
if user:
raise forms.ValidationError(
"That user is already taken , please select another ")
#check password
if password != password1:
raise forms.ValidationError(
"Your current and confirm password do not match.")
return cleaned_data
Can anyone spot what I'm doing wrong in the following example. Validating messages are not appearing in my template when incorrect details are entered such as a invalid email address. The template is loading and there are no errors.
I'm excepting validation messages to be printed on page, however for some reason this has suddenly stop working. As you can see from the code example below I'm passing the form in the context back to the template. this used to work and today just stopped.
view.py
if request.method == 'POST':
form = RegistrationForm(request.POST)
if form.is_valid():
# If form has passed all validation checks then continue to save member.
user = User.objects.create_user(
username=form.cleaned_data['username'],
email=form.cleaned_data['email'],
password=form.cleaned_data['password']
)
user.save()
#member = User.get_profile()
#member.name = form.cleaned_data['name']
#member.save()
member = Member(
user=user,
name=form.cleaned_data['name']
)
member.save()
# Save is done redirect member to logged in page.
return HttpResponseRedirect('/profile')
else:
# If form is NOT valid then show the registration page again.
form = RegistrationForm()
context = {'form':form}
return render_to_response('pageRegistration.html', context,context_instance=RequestContext(request))
form.py
class RegistrationForm(ModelForm):
username = forms.CharField(label=(u'User Name'))
email = forms.EmailField(label=(u'Email'))
password = forms.CharField(label=(u'Password'), widget=forms.PasswordInput(render_value=False))
passwordConfirm = forms.CharField(label=(u'Confirm Password'), widget=forms.PasswordInput(render_value=False))
class Meta:
model = Member
# Don't show user drop down.
exclude = ('user',)
def clean_username(self):
username = self.cleaned_data['username']
try:
User.objects.get(username=username)
except User.DoesNotExist:
return username
raise forms.ValidationError("Username already taken.")
def clean(self):
try:
cleaned_data = super(RegistrationForm, self).clean()
password = cleaned_data.get("password")
passwordConfirm = cleaned_data.get('passwordConfirm')
if password != passwordConfirm:
raise forms.ValidationError("Password does not match, try again.")
return cleaned_data
except:
raise forms.ValidationError("Error")
pageRegistration.html
<form action="" method="POST">
{% csrf_token %}
{% if forms.errors %}
<p>
correct some stuff
</p>
{% endif %}
{{form}}
<br>
<input type="submit" value="submit">
</form>
Since, the form is not validate in the else clause your form variable is overriden with a new form where it looses all of the errors
if request.method == 'POST':
form = RegistrationForm(request.POST)
if form.is_valid():
# If form has passed all validation checks then continue to save member.
user = User.objects.create_user(
username=form.cleaned_data['username'],
email=form.cleaned_data['email'],
password=form.cleaned_data['password']
)
user.save()
#member = User.get_profile()
#member.name = form.cleaned_data['name']
#member.save()
member = Member(
user=user,
name=form.cleaned_data['name']
)
member.save()
# Save is done redirect member to logged in page.
return HttpResponseRedirect('/profile')
return render_to_response('pageRegistration.html', context,context_instance=RequestContext(request))
Updated for the CBV world.
This is what was causing the equivalent error for me:
class CreateView(generic.CreateView): # or generic.UpdateView
def get_context_data(self, **kwargs):
context_data = super(CreateView, self).get_context_data(**kwargs)
# context_data['form'] = self.form_class # << this was the problematic override
Perhaps the page is returning a new form every time it reloads. Check if the
context variable in views.py contains 'form' : form
My forms.py file:
class RegisterForm(ModelForm):
"""This form lets people register as members."""
help_string = "Please choose a password that is at 6 characters long,"\
"and contains at least on speacial character or number"
First_Name = forms.CharField(max_length=50)
Last_Name = forms.CharField(max_length=50)
Username = forms.CharField(max_length=50)
Password = forms.CharField(max_length=50)
Confirm_Password = forms.CharField(max_length=50)
Email_Address = forms.EmailField()
Address = forms.CharField(widget=forms.Textarea)
def save(self, commit=True):
cd = self.cleaned_data
u = User.objects.create_user(
username=self.cleaned_data['Username'],
email=self.cleaned_data['Email_Address'],
password=self.cleaned_data['Password'],
)
u.is_staff = True
u.save()
u.First_Name = self.cleaned_data['First_Name']
u.Last_Name = self.cleaned_data['Last_Name']
m = self.instance
m.user = u
if not commit:
return [m, u]
u.save()
m.save()
return m
My views.py file:
def register(request):
if request.method == "POST":
form = RegisterForm(request.POST)
if form.is_valid():
try:
instance = form.save()
return HttpResponseRedirect('/registered/')
except:
return HttpResponseRedirect('/validation/')
else:
form = RegisterForm()
return render_to_response(
'homepage/register.html',
{'form':form,},
context_instance=RequestContext(request),
)
My register.html template:
<h4>Register</h4>
<form action="" method="POST">
<table border="0" cellpadding="1" cellspacing="1" id="eric">
<tr>
<td>{{ form.as_table }}</td>
</tr>
<tr>
<td></td>
<td>
<input type="submit" value="Create Account">
<input type="Reset" value="Clear"></td>
</tr>
</table>
</form>
The thing what it does in views.py is skip the try block and execute the except.
What should I do or change?
So, You are saving the data twice. And in your model definition username must be unique. So, throwing integrity error. You are saving data in
1.) Forms save
2.) again same data you are saving in Views.
My suggestion.
clean your data in the forms.
Remove save() from forms.
save form in views.
class RegisterForm(ModelForm):
"""This form lets people register as members."""
help_string = "Please choose a password that is at 6 characters long,"\
"and contains at least on speacial character or number"
First_Name = forms.CharField(max_length=50)
Last_Name = forms.CharField(max_length=50)
Username = forms.CharField(max_length=50)
Password = forms.CharField(max_length=50)
Confirm_Password = forms.CharField(max_length=50)
Email_Address = forms.EmailField()
Address = forms.CharField(widget=forms.Textarea)
def clean_name(self,):
username = self.cleaned_data['Username']
return username
def clean_email(self,):
email = self.cleaned_data['Email_Address']
param = {'email': email}
if dbapi.get_user(**param):
raise ValidationError('Email already registered')
return email
def clean_password(self,):
// your logic here
In views.
Not resembles your code
All values are dummy here You just fit according to your values
register_name should be the instance of your Form
username = register_form.cleaned_data['username']
email = register_form.cleaned_data['email']
password = register_form.cleaned_data['password']
name = register_form.cleaned_data['name']
# Create a user obj
user_obj = create_user(username, email, password) // to create a user_obj
# https://docs.djangoproject.com/en/dev/topics/auth/#creating-users
user_obj.first_name = 'xxxxxxxxx'
user_obj.last_name = 'xxxxxxxxxx'
user_obj.save()
Ok. I am writting here a create_user method:
from django.contrib.auth.models import User
def create_user(username, email, password):
# This will return the user_obj
return User.objects.create_user(username, email, password)
Since you are using ModelForm, I suggest you remove the 'except' in your registration function. It should look like this:
def register(request):
if request.method == "POST":
form = RegisterForm(request.POST)
if form.is_valid():
instance = form.save()
return HttpResponseRedirect('/registered/')
else:
form = RegisterForm()
return render_to_response(
'homepage/register.html',
{'form':form,},
context_instance=RequestContext(request),
)
The reason of removing the 'except' is that you are already using modelform and it provides you with form validations. You don't have to create a template telling the user that their input is invalid (that is if you are using /validation/ to tell the user that they have invalid input).