I have a signup form which I have defined below
forms.py
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
from django import forms
class SignUpForm(UserCreationForm):
display_name = forms.CharField(max_length=30, required=True, help_text='Please provide a display name for your profile')
class Meta:
model = User
fields = ('username', 'password1', 'password2', 'display_name')
In the views.py, I handle the signup process
views.py
from django.contrib.auth.models import User
from django.contrib.auth import login, authenticate
from .forms import SignUpForm
from django.shortcuts import render, redirect
#csrf_exempt
def signup_users(request):
if request.method == 'POST':
form = SignUpForm(request.POST)
if form.is_valid():
user = form.save(commit=False)
username = form.cleaned_data.get('username')
display_name = form.cleaned_data.get('display_name')
raw_password = form.cleaned_data.get('password1')
user.set_password(raw_password)
user.display_name = display_name
user.save()
user = authenticate(username=username, password=raw_password)
print("signup authencticate", user)
login(request, user)
return render(request, 'index.html')
else:
form = SignUpForm()
return render(request, 'signup.html', {'form': form})
The user is able to signup successfully however their display_name doesn't get stored in the django User model.Even in the django admin, I do not see the field display_name.I have even performed a query like serializers.serialize("json",User.objects.filter(username=username)) but even here it shows every other field except the display_name.
What am I doing wrong?
Well quite simply the django.contrib.auth.models.User model has not field named display_name so of course it doesn't get saved. If you want to add fields to your User model you'll have to provide a custom User model.
Related
I am following a tutorial to do this in Django 3.1.7.
The problem I'm having here is I'm being forced to repeat my Profile Model in my Profile Form definition.
I want to use forms.ModelForm in my forms.py to inherit my Profile Model and auto-generate the forms. It seems redundant to have to spell everything out again in forms.py when it is already defined in my Models. But I'm not sure how to do that with this architecture.
I've tried this approach:
https://stackoverflow.com/a/2213802/4144483
But the problem with this is that UserForm is incomplete - 'password1' and 'password2' don't exist for model User. This is not a good solution for user registration. I seem to be bound to using UserCreationForm somehow.
#models.py
from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.dispatch import receiver
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
bio = models.TextField(max_length=500, blank=True)
location = models.CharField(max_length=30, blank=True)
birth_date = models.DateField(null=True, blank=True)
#receiver(post_save, sender=User)
def update_user_profile(sender, instance, created, **kwargs):
if created:
Profile.objects.create(user=instance)
instance.profile.save()
#forms.py
rom django import forms
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
class SignUpForm(UserCreationForm):
birth_date = forms.DateField(help_text='Required. Format: YYYY-MM-DD')
class Meta:
model = User
fields = ('username', 'birth_date', 'password1', 'password2', )
#views.py
from django.contrib.auth import login, authenticate
from django.shortcuts import render, redirect
from mysite.core.forms import SignUpForm
def signup(request):
if request.method == 'POST':
form = SignUpForm(request.POST)
if form.is_valid():
user = form.save()
user.refresh_from_db() # load the profile instance created by the signal
user.profile.birth_date = form.cleaned_data.get('birth_date')
user.save()
raw_password = form.cleaned_data.get('password1')
user = authenticate(username=user.username, password=raw_password)
login(request, user)
return redirect('home')
else:
form = SignUpForm()
return render(request, 'signup.html', {'form': form})
I generally use ModelForm instead of CreateUserForm for UserRegistration like this and add password1 and password2 fields in it. also, I check if they both are the same.:
forms.py
class UserRegistrationForm(forms.ModelForm):
password = forms.CharField(label='Password', widget=forms.PasswordInput)
password2 = forms.CharField(label='Repeat Password', widget=forms.PasswordInput)
email = forms.EmailField(label='Email')
date_of_birth = forms.DateField(widget=forms.widgets.DateInput(attrs={'type': 'date'}))
class Meta:
model = User
fields = ['username', 'first_name', 'last_name', 'email',
] #these ordering will be as follow in html form
def clean_password2(self):
cd = self.cleaned_data
if cd['password'] != cd['password2']:
raise forms.ValidationError("Passwords don't match")
return cd['password2']
Then in views, I create a user and their profile and save the password in encrypted form, and link their profile.
views.py
def register(request):
u_form = UserRegistrationForm(data=request.POST or None)
p_form = ProfileForm(data=request.POST or None, files=request.FILES or None)
if u_form.is_valid() and p_form.is_valid():
new_user = u_form.save(commit=False)
new_user.set_password(u_form.cleaned_data['password']) #this saves password in encrypted form instead of raw password
new_user.save()
profile = p_form.save(commit=False)
profile.user = new_user
profile.save()
return render(request, 'accounts/register_done.html', {'new_user': user})
return render(request, 'accounts/register.html', {'user_form': u_form, 'profile_form':p_form})
You can modify it as you like.
I am new to Django and I am trying to make my first registration app. I used the UserCreationForm. When I run the code and try to register, if I put the same email form many user it doesn't give me any error.
My forms.py
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
class RegisterForm(UserCreationForm):
class Meta:
model = User
fields = ['username', 'email', 'password1', 'password2']
my views.py
from django.shortcuts import render, redirect
from django.contrib.auth import authenticate, login, logout
from django.contrib import messages
# Create your views here.
from .forms import RegisterForm
def registerUser(request):
form = RegisterForm()
if request.method == 'POST':
form = RegisterForm(request.POST)
if form.is_valid():
form.save()
return redirect('login')
else:
form = RegisterForm()
return render(request, 'register.html', {'form':form})
def loginUser(request):
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
if username and password:
user = authenticate(username=username, password=password)
if user is not None:
login(request, user)
return redirect('home')
else:
messages.error(request, 'Username or Password is Incorrect')
else:
messages.error(request, 'Fill out all the fields')
return render(request, 'login.html', {})
def home(request):
return render(request, 'home.html', {})
def logoutUser(request):
logout(request)
return redirect('home')
def Profile(request):
return render(request, 'profile.html', {})
As said by Harshil Suthar in the comments, overriding the default user model is the best practise (https://docs.djangoproject.com/en/3.1/topics/auth/customizing/#a-full-example), but it may be a lot of effort in your case if you just want to check unique email when using your form.
You can solve this problem using the clean_< attribute > method of your form. Note that it will just be effective when using this form. So, for example a superuser will still be able to have the same email as another user...
# Other imports...
from django.core.exceptions import ValidationError
class RegisterForm(UserCreationForm):
class Meta:
model = User
fields = ['username', 'email', 'password1', 'password2']
def clean_email(self):
email = self.cleaned_data["email"]
if User.objects.filter(email=email).exists():
raise ValidationError("An user with this email already exists!")
return email
I'm trying to add data from UserCreationForm extra fields to database, i want to add multiple fields to UserCreationForm and save it to database. I saw other examples from topics here in stackoverflow, but it doesn't work.
Here is a example of my code:
( fields: "agree_terms" or "price" could be anything else)
forms.py
from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
class UserRegisterForm(UserCreationForm):
email = forms.EmailField(widget = forms.EmailInput(attrs=
{'placeholder':'Email'}))
agree_terms = forms.BooleanField()
price = forms.DecimalField(decimal_places=2, max_digits=10000)
class Meta(UserCreationForm.Meta):
model = User
fields = UserCreationForm.Meta.fields + ('username', 'password1',
'email','password2','agree_terms','price')
views.py
#csrf_protect
def registers(request):
if request.method == 'POST':
form = UserRegisterForm(request.POST)
print(form)
print(form.is_valid())
if form.is_valid():
form.save()
username = form.cleaned_data.get('username')
messages.success(request,'Conta criada {}'.format(username))
return redirect('login')
else:
form = UserRegisterForm()
return render(request,'header-login.html',{'form':form})
Did you also changed your User model to support those fields? You'd need to add them to the model/table as well.
Although, I wouldn't recommend piling up so much extra data directly on the User model.
I am trying to filter user's alias. I am using Django's userform and its authentication.
forms.py
from django import forms
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
class SignupForm(UserCreationForm):
email = forms.CharField(
retuired=True,
widget=EmailInput(
attrs={'class':'validate',}
)
)
views.py
from django.shortcuts import render,redirect
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth import login as auth_login
def signup(req):
if req.method == "POST":
form = UserCreationForm(req.POST)
if form.is_valid():
user = form.save()
auth_login(req, user)
return redirect('home')
else:
form = UserCreationForm()
context = {
'form':form,
}
return render(req, "signup.html", context)
I believe that I need to filter inside of views.py. For example, if I want to filter alias which is not gmail, they cannot signup. How can I filter email?
Thanks in advance!
You can use clean_<field_name> method.
def clean_email(self):
email = self.cleaned_data['email']
if not email.endswith('gmail.com'):
raise forms.ValidationError("Invalid email", code='invalid email')
return email
https://docs.djangoproject.com/en/1.11/ref/forms/validation/#cleaning-a-specific-field-attribute
First attempt at trying to create a student user by extending the User model.
Issue: Upon clicking register btn i.e.Login (btn) instead of
redirecting to home it shows the following: NameError at /register/
...name 'user' is not defined
File "E:\ifb299\tutorial2\accounts\views.py", line 33, in register
Students.objects.create(user=user) NameError: name 'user' is not defined [25/Mar/2018 14:38:07] "POST /register/ HTTP/1.1" 500 67801
Not really sure what I'm doing wrong, why is Students.objects.create(user=user) wrong and how do i fix it, please?
views.py
from django.shortcuts import render
from django.shortcuts import redirect
from accounts.forms import RegistrationForm, EditProfileForm
from django.contrib.auth.models import User
from accounts.models import Students
from django.contrib.auth.forms import UserChangeForm
from django.http import HttpResponse
from django.contrib.auth.decorators import login_required
def home(request):
return render(request, 'accounts/home.html')
def login_redirect(request):
return redirect('/login/')
def register(request):
# Once register page loads, either it will send to the server POST data (if the form is submitted), else if it don't send post data create a user form to register
if request.method == "POST":
form = RegistrationForm(request.POST)
if form.is_valid():
form.save()
Students.objects.create(user=user)
return redirect('../home/')
else:
# Create the django default user form and send it as a dictionary in args to the reg_form.html page.
form = RegistrationForm()
args = {'form': form}
return render(request, 'accounts/reg_form.html', args)
#login_required
def view_profile(request):
args = {'user': request.user}
return render(request, 'accounts/profile.html', args)
#login_required
def edit_profile(request):
# Handle post request - if the user submits a form change form details and pass the intance user
if request.method == 'POST':
form = EditProfileForm(request.POST, instance=request.user)
if form.is_valid():
form.save()
return redirect('../profile')
# Handles the get request - if no post info is submitted then get the form and display it on the edit profile page.
else:
form = EditProfileForm(instance=request.user)
args = {'form': form}
return render(request, 'accounts/profile_edit.html', args)
models.py
from django.db import models
from django.contrib.auth.models import AbstractUser
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.db.models.signals import *
from django.conf import settings
class Students(AbstractUser):
bio = models.TextField(max_length=500, blank=True)
location = models.CharField(max_length=30, blank=True)
birth_date = models.DateField(null=True, blank=True)
forms.py
from django import forms
from django.contrib.auth.models import User
from .models import *
from django.contrib.auth.forms import UserCreationForm, UserChangeForm
from betterforms.multiform import MultiModelForm
from django.contrib.auth.forms import UserCreationForm
# Create a custom form that inherites form UserCreationForm (adding our own fields to save i db)
# Inheriting form in the paramters ()
class RegistrationForm(UserCreationForm):
email = forms.EmailField(required=True)
class Meta:
model = Students
fields = (
'username',
'first_name',
'last_name',
'email',
'password1',
'password2',
'bio',
'location',
'birth_date',
)
def save(self, commit=True):
user = super(RegistrationForm, self).save(commit=False)
user.first_name = self.cleaned_data['first_name']
user.last_name = self.cleaned_data['last_name']
user.email = self.cleaned_data['email']
if commit:
user.save()
return user
# Inherits from UserChangeForm class - we keep everything i.e. methods, functionality same but change the things we want to show - connected to the User model
class EditProfileForm(UserChangeForm):
class Meta:
model = User
# Create fields variable get has all the fields we want to show
fields = (
'email',
'first_name',
'last_name',
'password'
)
first, you did not save the return value of form.save() to the variable user.
second, there is no field user your model Student.