When new users register I want to store:
fields = ['username', 'email', 'password1', 'password2', 'city']
so I extended UserRegisterForm by adding 'city' to the form.
It renders fine in the template and save everything except 'city'. There is no even column 'city' in the new users profile when checking by admin page so looks like its not creating one.
I found few similar posts and been following Doc but that didint help.
Have tried many different ways but will post two I think mostly sensible ones.
EXAMPLE 1
- *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()
city = forms.CharField(required=True)
class Meta:
model = User
fields = ['username', 'email', 'password1', 'password2', 'city']
def save(self, commit=True):
user = super(UserRegisterForm, self).save(commit=False)
user.city = self.cleaned_data['city']
if commit:
user.save()
return user
- *views.py*
...
from django.contrib.auth.forms import UserCreationFormfrom
from .forms import UserRegisterForm
def register(request):
if request.method == 'POST':
form = UserRegisterForm(request.POST)
if form.is_valid():
form.save()
print('VALID')
username = form.cleaned_data.get('username')
messages.success(request,
'{} Your account has been created! You can now Log In'.format(username))
return redirect('/login/')
else:
form = UserRegisterForm()
context = {
'form': form,
}
return render(request, 'users/register.html', context)
@login_required
def profile(request):
return render(request, 'users/profile.html')
- *template*
...
<form method="POST">
{% csrf_token %}
{{ form|crispy }}
<!-- {{ form2 }} -->
<button class="btn-signup" type="submit">Sign Up</button>
</form>
In Example 2 Iam creating new class 'ProfileForm' with new model as separate form and including it in the views.py in one function with UserRegisterForm.
EXAMPLE 2
- *models.py*
...
class Profile(models.Model):
city = models.CharField(max_length=25, blank=False)
def __str__(self):
return self.city
- *forms.py*
...
class UserRegisterForm(UserCreationForm):
email = forms.EmailField()
city = forms.CharField(required=True)
class Meta:
model = User
fields = ['username', 'email', 'password1', 'password2', 'city']
class ProfileForm(forms.ModelForm):
class Meta:
model = Profile
fields = ['city']
def save(self, commit=True):
user = super(UserRegisterForm, self).save(commit=False)
user.city = self.cleaned_data['city']
if commit:
user.save()
return user
- *views.py*
...
from django.contrib.auth.forms import UserCreationFormfrom
from .forms import UserRegisterForm, ProfileForm
def register(request):
if request.method == 'POST':
form = UserRegisterForm(request.POST)
form2 = ProfileForm(request.POST)
if form.is_valid() and form2.is_valid():
form.save()
form2.save()
print('VALID')
username = form.cleaned_data.get('username')
messages.success(request,
'{} Your account has been created! You can now Log In'.format(username))
return redirect('/login/')
else:
form = UserRegisterForm()
form2 = ProfileForm()
context = {
'form': form,
'form2': form2
}
return render(request, 'users/register.html', context)
- *template*
...
<form method="POST">
{% csrf_token %}
{{ form|crispy }}
{{ form2 }}
<button class="btn-signup" type="submit">Sign Up</button>
</form>
Your Profile
model should have a OneToOne
relation with the User
model like this:
Class Profile (models.Model):
user = models.OneToOneField (User,on_delete=models.CASCADE)
city = models.CharField (max_length=25,blank=False)
You don't need to define ProfileForm.You can create profile objects for the user like this.
form = UserRegisterForm (request.POST)
if form.is_valid ():
city = form.cleaned_data ['city']
user = form.save ()
Profile.objects.create (user=user,city=city)
return redirect ('some_view)