I extended User (django.contrib.auth.models) with a profile (UserProfile). I have a problem to implement a view where I can edit both, User and UserProfile in one form.
The issue I have is quite simple: only “main” form is saved. Additional one is not saved.
Please help to get it fixed as I’m totally out of options now. I use Django 3.1.7.
Models:
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
picture = models.ImageField(default='users/default_user.png', upload_to='users', blank=True, null=True)
Forms:
class UserUpdateForm(UserChangeForm):
class Meta:
model = User
fields = ['first_name', 'last_name']
class ProfileUpdateForm(forms.ModelForm):
class Meta:
model = UserProfile
fields = ['picture']
The generic class-based views are only designed to work with one form/model.
<opinion> The easiest way to handle this is to not create a second form. Add the two name fields from your UserUpdateForm as form fields in ProfileUpdateForm. Then, override the form’s save method to take those two fields and use them to update the corresponding User model. <opinion>
I flagged the above as an opinion, because there are other ways to handling it. However, I think that’s the easiest way.
Ok, I’m confused here by this snippet. What other changes have you made to the code? Did you add the User fields to the Profile form, or did you add the Profile field to the User form?
Also, for clarity, when you call the save method of a model form, the return value is not a form - it’s the model that has been saved. (Or is prepared to be saved with the commit=False). Calling it “user_form” is misleading - if the form is the User form, then what you have at that point is a User object.
Always keep in mind that a ModelForm is just a form, where Django adds some magic to associate that form with a Model. It doesn’t remove any functionality of a form.
class ProfileUpdateForm(forms.ModelForm):
first_name = forms.CharField(max_length=32)
last_name = forms.CharField(max_length=32)
class Meta:
model = UserProfile
fields = ['picture']
So then your view will end up looking something like this:
But there is no need for you to do the “double save” on the profile model. You’re not modifying the profile model in this method, and the related User model must already exist.
Without this last save it was not working, when I modified the fields which belongs to UserProfile itself (like picture and more I have). Use case was: edit first_name and eg. picture at once.
user.save is saving data for User model and profile.save for UserProfile model.