Several forms in one page by UpdateView

I have a user model and a profile model and I want to update both of them with a url. Only I don’t know how I can show several forms on a page using UpdateView or any other method and validate and save them.
code:
models:

class User(AbstractBaseUser, PermissionsMixin):
    username = models.CharField(max_length=50, unique=True)
    roles = models.ManyToManyField('Role', related_name='users')
    is_active = models.BooleanField(default=True)
    is_staff = models.BooleanField(default=False)
    is_superuser = models.BooleanField(default=False)
    created_date = models.DateTimeField(auto_now_add=True)
    updated_date = models.DateTimeField(auto_now=True)

    USERNAME_FIELD = 'username'
    REQUIRED_FIELDS = []

    objects = UserManager()

    def __str__(self):
        return self.username


class Profile(models.Model):
    image = models.ImageField(upload_to='profile_pics/', default='../static/img/default-user-avatar.png', blank=True, null=True)
    user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='profile')
    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)
    description = models.TextField(blank=True)
    created_date = models.DateTimeField(auto_now_add=True)
    updated_date = models.DateTimeField(auto_now=True)

    def get_full_name(self):
        return f'{self.first_name} {self.last_name}'

    def __str__(self):
        return self.get_full_name()

forms:

class UserForm(forms.ModelForm):
    class Meta:
        model = models.User
        fields = 'username',


class UserProfileForm(forms.ModelForm):
    class Meta:
        model = models.Profile
        exclude = 'user',

urls:

app_name = 'dashboard'

urlpatterns = [
    path('profile/', views.ProfileUpdateView.as_view(), name='profile')
]

If there is a way that I can do this using UpdateView or cbv, it would be better, but if using fbv or adding modelForms to create a modelForm is also good

The Django-provided edit CBVs are designed to work with one instance of one model. You can create a CBV to work with multiple models (we’ve done that), but the Django-provided edit CBVs aren’t the best way to do it. (You would probably want to use View as the base class.)

If you are going to render multiple Django forms within a single HTML <form> element, you will want to use the prefix attribute with each form.

Validating and saving them is something that you will need to do for each form.

1 Like

did you check formset_factory or modelformset_factory?

In my opinion the correct solution for this specific case is to not have a Profile model at all, but instead put those fields on the User custom model directly. I have made the mistake of using a Profile model and always regretted it.

That being said, crossing FK, m2m and one-to-one relationships is quite easy to do in iommi forms. You might want to check that out. (Full disclosure, I’m one of the authors. I built iommi forms because of my many frustrations with Django forms, this being one of them).

This is not universally a good solution. There are any number of situations where the implementation of a custom User model is not the right answer.

  • You have an existing project, and going through the work of switching to a custom user is not worth the effort involved.

  • You have a “heavy” profile, where the instantiation of the User model with every request becomes a problem.

  • You have “conditional” profiles, where attributes may or may not exist based upon characteristics of the user, and those sets of characteristics may or may not overlap.

  • You are tied to third-party projects or libraries that don’t allow for custom users - they are hard-coded to expect to find user data in django.auth.User. (Sadly, those do exist.)

Our philosophy is to go in the other direction. We prefer a “thin User”, and instead build around the concept of “strong Profiles”. It has worked extremely well for us.

It’s not that hard. And it’s well worth the effort imo.

Deferred attributes can solve that.

Ok, this one I haven’t heard of. I would probably suggest a hard fork if you really want to use such a broken library :stuck_out_tongue:

In any case, this specific case is very clearly the case of having very few extra fields so none of your caveats apply.

To do what I said, do you suggest that I use View as base class and create all validations from scratch?