I posted this question but I couldn't get the solutions provided to work. Instead of editing, I'm posting a new one with the modified code which uses a different approach (with two model forms)
models.py
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='profile')
location = models.CharField(max_length=30, blank=True)
birth_date = models.DateField(null=True, blank=True)
def __str__(self):
return self.user.username
def create_profile(sender, **kwargs):
user = kwargs["instance"]
if kwargs["created"]:
user_profile= Profile(user=user)
user_profile.save()
post_save.connect(create_profile, sender=User)
forms.py
from django_superform import FormField, SuperForm
class SignUpForm(UserCreationForm):
password1 = forms.CharField(label=("Password"), widget=forms.PasswordInput)
password2 = forms.CharField(label=("Confirm password"), widget=forms.PasswordInput)
class Meta:
model = User
fields = ('username', 'first_name', 'last_name', 'email')
labels = {
'username': ('Capser name'),
}
class ProfileForm(forms.ModelForm):
class Meta:
model = Profile
fields = ('location', 'birth_date')
class SuperProfile(SuperForm):
signupform = FormField(SignUpForm)
profileform = FormField(ProfileForm)
See that I'm using the Superform from Django-superform package. The reason for that is that I'm uing a form template in my html template as explained later in the template section.
templates
html page template : registration_form.html
<form class="form-horizontal" action="" method="POST" enctype="multipart/form-data">
{% csrf_token %}
<h1>Create a capser account</h1>
<table border="1">
{{ userform.as_table }}
{{ profileform.as_table }}
</table>
{% include 'home/form-template.html' %}
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-success">Create account</button>
</div>
</div>
</form>
form template : form-template.html
{% if messages %}
<ul>
{% for message in messages %}
<li>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
{% for field in form %}
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<span class="text-danger small">{{ field.errors }}</span>
</div>
<label class="control-label col-sm-2">{{ field.label_tag }}</label>
<div class="col-sm-10">{{ field }}</div>
<div class="col-sm-offset-2 col-sm-10">
<span class="text-danger small">{{ field.help_text }}</span>
</div>
</div>
{% endfor %}
and the views.py with the new approach (importing fields from the two model forms
views.py
class UserFormView(View):
Userform_class = SignUpForm
Profileform_class = ProfileForm
template_name = 'home/registration_form.html'
#display a blank form
def get(self, request):
userform = self.Userform_class(None)
profileform=self.Profileform_class(None)
return render (request, self.template_name, {'userform': userform, 'profileform': profileform})
#process form data
def post(self, request):
userform = self.Userform_class(request.POST)
profileform = self.Profileform_class(request.POST)
if userform.is_valid() and profileform.is_valid():
user = userform.save(commit=False)
#user.refresh_from_db() # load the profile instance created by the signal
password = userform.cleaned_data['password1']
user.set_password(password)
username = userform.cleaned_data['username']
first_name=userform.cleaned_data['first_name']
last_name=userform.cleaned_data['last_name']
email = userform.cleaned_data['email']
user.save()
new_profile = user_profile.objects.get(user = request.user)
new_profile.objects.create(
user=user,
location=profileform.cleaned_data.get('location'),
birth_date=profileform.cleaned_data.get('birth_date'))
new_profile.save()
#return user objects if credentials are correct
user = authenticate(username=username, password=password)
if user is not None:
if user.is_active:
login(request, user)
return redirect('home:home')
return render (request, self.template_name, {'userform': userform, 'profileform':profileform})
Now when I submit my form, I get the following error : name 'user_profile' is not defined
I thought that the user_profil
e was the instance created at the end of my model.py
file.
So if this doesn't work like so, how do I call the instance of my Profile model in the view ?
I've tried a lot of solutions and none worked so far.
Also, I initially wanted to use my form-template in order to display my form on the html page, but now that I use two model forms userform and profileform, I wonder on how to use my form template (I tried with Superform without success).
The error says it itself,
user_profile
is not defined. A part of your code is not correct in your views. You should deal with Django User Model, and after creating the instance, call your modelProfile
which is linked byOneToOneField
to User from youryour_app.models
That issue UNIQUE constraint failed: home_profile.user_id is because of the signal
post_save
is called by doingnew_profile.save()
. When it's called, it creates another profile with the sameuser
, whereasuser
is already linked to the Profile when you had callednew_profile.save()
which has anOneToOneField()
withUser
. So just remove the signal