title: Django Class BasedView - UpdateView with multiple models and multiple forms
body: <p>I have a list of users or users/roles type.
  I want to be able to click a link to Update their respective profiles users.</p>
  
  <p>When I perform click in Profile user, I should be able to edit the associated data to respective user according to profile that handle each of them. Each data profile is the simple page or template and manage for the same <code>UpdateView</code> class based view.</p>
  
  <p>In detail my scenario is the following:</p>
  
  <p>I have the <code>User</code> (inherit from <code>AbstractBaseUser</code>) model and here I manage the account data of the all users, this mean all data in common to all users roles or types which I want manage in my application such as:</p>
  
  <ul>
  <li>user student</li>
  <li>user professor</li>
  <li>user executive</li>
  </ul>
  
  <p>This users/roles type have their own model in where I define the respective fields to each of them. So, I have too, <code>StudentProfile</code> <code>ProfessorProfile</code> and <code>ExecutiveProfile</code> models, of this way:</p>
  
  <p>My <code>User</code> model is:</p>
  
  <pre><code>class User(AbstractBaseUser, PermissionsMixin):
  
      email = models.EmailField(unique=True)
  
      username = models.CharField(max_length=40, unique=True)
  
      slug = models.SlugField(
          max_length=100,
          blank=True
      )
  
      is_student = models.BooleanField(
          default=False,
          verbose_name='Student',
          help_text='Student profile'
      )
  
      is_professor = models.BooleanField(
          default=False,
          verbose_name='Professor',
          help_text='Professor profile'
      )
  
      is_executive = models.BooleanField(
          default=False,
          verbose_name='Executive',
          help_text='Executive profile',
      )
  
      other fields ...
  
      def get_student_profile(self):
          student_profile = None
          if hasattr(self, 'studentprofile'):
              student_profile = self.studentprofile
          return student_profile
  
      def get_professor_profile(self):
          professor_profile = None
          if hasattr(self, 'professorprofile'):
              professor_profile = self.professorprofile
          return professor_profile
  
      def get_executive_profile(self):
          executive_profile = None
          if hasattr(self, 'executiveprofile'):
              executive_profile = self.executiveprofile
          return executive_profile
  
      def save(self, *args, **kwargs):
      user = super(User,self).save(*args,**kwargs)
  
      # Creating an user with student profile
      if self.is_student and not StudentProfile.objects.filter(user=self).exists():
          student_profile = StudentProfile(user = self)
          student_slug = self.username
          student_profile.slug = student_slug
          student_profile.save()
  
      # Creating an user with professor profile
      elif self.is_professor and not ProfessorProfile.objects.filter(user=self).exists():
          professor_profile = ProfessorProfile(user=self)
          professor_slug = self.username
          professor_profile.slug = professor_slug
          professor_profile.save()
  
      # Creating an user with executive profile
      elif self.is_executive and not ExecutiveProfile.objects.filter(user=self).exists():
          executive_profile = ExecutiveProfile(user = self)
          executive_slug = self.username
          executive_profile.slug = executive_slug
          executive_profile.save()
  
  # I have this signal to get the username and assign to slug field 
  @receiver(post_save, sender=User)
  def post_save_user(sender, instance, **kwargs):
      slug = slugify(instance.username)
      User.objects.filter(pk=instance.pk).update(slug=slug)
  </code></pre>
  
  <p>The idea behind of these schema is that when I create and user with <code>is_student</code> field checked the <code>StudentProfile</code> model is used for complete their data. </p>
  
  <p>When I create and user with <code>is_professor</code> field checked the <code>ProfessorProfile</code> model is used for complete their data.</p>
  
  <p>When I create and user with <code>is_executive</code> field checked the <code>ExecutiveProfile</code> model is used for complete their data.</p>
  
  <p>The models for each Profile (<code>Student</code>, <code>Professor</code> and <code>Executive</code>) are such as follow:</p>
  
  <pre><code>class StudentProfile(models.Model):
      user = models.OneToOneField(
          User,
          on_delete=models.CASCADE
      )
  
      slug = models.SlugField(
          max_length=100,
          blank=True
      )
  
      origin_education_school = models.CharField(
          _("origin education institute"), max_length=128
      )
  
      current_education_school = models.CharField(
          _("current education institute"), max_length=128
      )
  
      extra_occupation = models.CharField(
          _("extra occupation"), max_length=128
      )
  
  class ProfessorProfile(models.Model):
  
      CATHEDRAL_PROFESSOR = 'CATHEDRAL'
      RESEARCH_PROFESSOR = 'RESEARCH'
      INSTITUTIONAL_DIRECTIVE = 'DIRECTIVE'
  
  
      OCCUPATION_CHOICES = (
          (CATHEDRAL_PROFESSOR, 'Cathedral Professor'),
          (RESEARCH_PROFESSOR, 'Research Professor'),
          (INSTITUTIONAL_DIRECTIVE, 'Institutional Directive'),
      )
  
      user = models.OneToOneField(
          User,
          on_delete=models.CASCADE
      )
  
      slug = models.SlugField(
          max_length=100,
          blank=True
      )
  
      occupation = models.CharField(
          max_length=255,
          blank = False,
      )
  
  class ExecutiveProfile(models.Model):
  
      user = models.OneToOneField(
          User,
          on_delete=models.CASCADE
      )
  
      slug = models.SlugField(
          max_length=100,
          blank=True
      )
  
      occupation = models.CharField(
          max_length=255,
          blank = False,
      )
  
      enterprise_name = models.CharField(
          max_length=255,
          blank = False,
      )
  </code></pre>
  
  <p>I have the form to each profile update data of this way in my forms.py: </p>
  
  <pre><code>class UserUpdateForm(forms.ModelForm):
      class Meta:
          widgets = {
              'gender':forms.RadioSelect,
          }
          fields = ("username", "email", "is_student",
              "is_professor", "is_executive",)
          model = get_user_model() #My model User
  
  
  class StudentProfileForm(forms.ModelForm):
      class Meta:
          model = StudentProfile
          fields = ('origin_education_school', 'current_education_school',
              'extra_occupation')
  
  
  class ProfessorProfileForm(forms.ModelForm):
      class Meta:
          model = ProfessorProfile
          fields = ('occupation',)
  
  
  class ExecutiveProfileForm(forms.ModelForm):
      class Meta:
          model = ExecutiveProfile
          fields = ('occupation', 'enterprise_name', 'culturals_arthistic',
              'ecological')
  </code></pre>
  
  <p>In my class based view AccountSettingsUpdateView I update the data related to the model Users, this mean the Account Data</p>
  
  <pre><code>class AccountSettingsUpdateView(LoginRequiredMixin, UpdateView):
      model = get_user_model()
      form_class = forms.UserUpdateForm
      # success_url = reverse_lazy('dashboard')
      context_object_name = 'preferences'
  
      def get_context_data(self, **kwargs):
          context = super(AccountSettingsUpdateView, self).get_context_data(**kwargs)
  
          user = self.request.user
          if user.is_student:
              profile = user.get_student_profile()
              context.update({'userprofile': profile})
          elif user.is_professor:
              profile = user.get_professor_profile()
              context.update({'userprofile': profile})
          elif user.is_executive:
              profile = user.get_executive_profile()
              context.update({'userprofile': profile})
          return context
  </code></pre>
  
  <p>The url for the below view is this</p>
  
  <pre><code>url(r"^preferences/(?P&lt;slug&gt;[\w\-]+)/$",
          views.AccountSettingsUpdateView.as_view(),
          name='preferences'
      ),
  </code></pre>
  
  <p>This view <code>AccountSettingsUpdateView</code> works OK. </p>
  
  <pre><code>[02/Apr/2017 23:51:17] "GET /accounts/preferences/luisa/ HTTP/1.1" 200 18092
  </code></pre>
  
  <p>And, in my other view and only in this view I am updating the data related to the profile of each one of these users. this mean the profiles described above:</p>
  
  <pre><code>class AccountProfilesView(LoginRequiredMixin, UpdateView):
  
      # When I ask for user with Student Profile
      model = StudentProfile
      form_class = forms.StudentProfileForm
  
      # sending the form to ProfessorProfile 
      second_form_class = forms.ProfessorProfileForm
  
      # sending the form to ExecutiveProfile 
      third_form_class = forms.ExecutiveProfileForm
  
  
      success_url = reverse_lazy('dashboard')
      template_name = 'accounts/student_form.html'
  
      def get_context_data(self, **kwargs):
          context = super(AccountProfilesView, self).get_context_data(**kwargs)
          user = self.request.user
  
          if 'form' not in context:
              context['form'] = self.form_class(self.request.GET,
                  instance=user)
          if 'form2' not in context:
              context['form2'] = self.second_form_class(self.request.GET,
                  instance=user)
          '''
          if 'form3' not in context:
              context['form3'] = self.third_form_class(self.request.GET,
                  instance=user)
          '''
          if user.is_student:
              profile = user.get_student_profile()
              context.update({'userprofile': profile})
          elif user.is_professor:
              profile = user.get_professor_profile()
              context.update({'userprofile': profile})
          elif user.is_executive:
              profile = user.get_executive_profile()
              context.update({'userprofile': profile})
          return context 
  </code></pre>
  
  <p>And the url to this <code>AccountProfilesView</code> view is this</p>
  
  <pre><code>url(r"^profile/(?P&lt;slug&gt;[\w\-]+)/$",
          views.AccountProfilesView.as_view(
              model=ProfessorProfile),
              name='profile'
      ),
  </code></pre>
  
  <p>Note that in the url i am passing the <code>ProfessorProfile</code> model like parameter, despite that in the view <code>AccountProfilesView</code> body, I am defining the <code>StudentProfile</code> model, but what happen is that in the url the model = ProfessorProfile override to the model = StundentProfile which came from the view.</p>
  
  <p>In this moment if I am use the <code>luisa</code> user with profile <code>StudentProfile</code> and I going to the url <code>http://localhost:8000/accounts/profile/luisa/</code> 
  the url is not found:</p>
  
  <pre><code>[03/Apr/2017 01:20:25] "GET /accounts/profile/luisa/ HTTP/1.1" 404 1771
  Not Found: /accounts/profile/luisa/ 
  </code></pre>
  
  <p><a href="https://i.stack.imgur.com/TpZLA.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/TpZLA.png" alt="enter image description here"></a> </p>
  
  <p>But If I remove the attribute <code>model=ProfessorProfile</code> that I am passing like parameter in the URL, this mean that my url stay so:</p>
  
  <pre><code>url(r"^profile/(?P&lt;slug&gt;[\w\-]+)/$",      views.AccountProfilesView.as_view(), name='profile')  
  </code></pre>
  
  <p>The url <code>http://localhost:8000/accounts/profile/luisa/</code> is OK</p>
  
  <pre><code>[03/Apr/2017 01:28:47] "GET /accounts/profile/luisa/ HTTP/1.1" 200 4469
  </code></pre>
  
  <p>This happen because in the view persist the model=StudentProfile attribute.</p>
  
  <p>Until this point, if I am use an user with ProfessorProfile named david and I am going to their profile URL, this is not found </p>
  
  <pre><code>Not Found: /accounts/profile/david/
  [03/Apr/2017 01:30:19] "GET /accounts/profile/david/ HTTP/1.1" 404 1769
  </code></pre>
  
  <p>But I add again the attribute <code>model=ProfessorProfile</code> that I am passing like parameter in the URL, such as mentioned above, the url of david profile <code>ProfessorProfile</code> is OK. </p>
  
  <pre><code>[03/Apr/2017 01:33:11] "GET /accounts/profile/david/ HTTP/1.1" 200 4171
  </code></pre>
  
  <p><a href="https://i.stack.imgur.com/jhVF7.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/jhVF7.png" alt="enter image description here"></a></p>
  
  <p>The same inconvenient I have with the ExecutiveProfile user type.</p>
  
  <p>According to the previous behavioral, is of this way, which, I am defining the view to ask for the user type roles and render their respective form.
  But the inconvenient is that in my view <code>AccountProfilesView</code> I cannot pass or indicate more than One model.</p>
  
  <p>I am trying indicate one second model in my <code>AccountProfilesView</code> of this way:</p>
  
  <pre><code>class AccountProfilesView(LoginRequiredMixin, UpdateView):
      model = StudentProfile
      form_class = forms.StudentProfileForm
      second_form_class = forms.ProfessorProfileForm
      third_form_class = forms.ExecutiveProfileForm
      #success_url = reverse_lazy('dashboard')
      template_name = 'accounts/student_form.html'
  
      def get_context_data(self, **kwargs):
          context = super(AccountProfilesView, self).get_context_data(**kwargs)
          # Indicate one second model
          context['professor_profile'] = ProfessorProfile
  </code></pre>
  
  <p>But the result is the same</p>
  
  <p>In summary my question is:</p>
  
  <p>In the UpdateView class based view ...
  How to can I work with multiple model (more precisely three models <code>StudentProfile</code>, <code>ProfessorProfile</code> and <code>ExecutiveProfile</code>) to can render their respective model forms with the order of access to each profile page user?</p>
  
  <p>I want can perform this wuth any amount of ProfileUser that I have.</p>
  
  <p>I unknown if my schema User and ProfileUser model are good of if there is some better alternative of address this challenge.</p>
  
  <p><strong>UPDATE</strong></p>
  
  <p>According to the answer of <a href="https://stackoverflow.com/users/2821488/ma0-collazos">@Ma0 Collazos</a> their solution works great.</p>
  
  <p>In this moment the goal is can make a combination of the different profiles, and can render the forms of each profile. So, if an user have a is_professor and is_executive profile, can show in their profile view (<code>AccountProfilesView</code>) their forms respective, this mean that when I go to profile user, can I see the fields the forms professor and the fields the form executive</p>
  
  <p>With the order to get this purpose, I add the scenario in where an user have the combination of profiles in my <code>AccountProfilesView</code> such as follow:</p>
  
  <pre><code>class AccountProfilesView(LoginRequiredMixin, UpdateView):
      # All users can access this view
      model = get_user_model()
      template_name = 'accounts/profile_form.html'
      fields = '__all__'
  
      def get_context_data(self, **kwargs):
          context = super(AccountProfilesView, self).get_context_data(**kwargs)
          user = self.request.user
  
          if not self.request.POST:
              if user.is_student:
                  profile = user.get_student_profile()
                  context['userprofile'] = profile
                  context['form_student'] = forms.StudentProfileForm()
              elif user.is_professor:
                  profile = user.get_professor_profile()
                  context['userprofile'] = profile
                  context['form_professor'] = forms.ProfessorProfileForm()
              elif user.is_executive:
                  profile = user.get_executive_profile()
                  context['userprofile'] = profile
                  context['form_executive'] = forms.ExecutiveProfileForm()
              elif user.is_student and user.is_professor and user.is_executive:
                  student_profile = user.get_student_profile()
                  professor_profile = user.get_professor_profile()
                  executive_profile = user.get_executive_profile()
  
                  context['student_profile'] = student_profile
                  context['professor_profile'] = professor_profile
                  context['executive_profile'] = executive_profile
  
                  context['form_student'] = forms.StudentProfileForm()
                  context['form_professor'] = forms.ProfessorProfileForm()
                  context['form_executive'] = forms.ExecutiveProfileForm()
  
          return context
  
      def post(self, request, *args, **kwargs):
          self.object = self.get_object()
          user = self.request.user
          if user.is_student:
              context['form_student'] = forms.StudentProfileForm(self.request.POST)
          elif user.is_professor:
              context['form_professor'] = forms.ProfessorProfileForm(self.request.POST)
          elif user.is_executive:
              context['form_executive'] = forms.ExecutiveProfileForm(self.request.POST)
          elif user.is_student and user.is_professor and user.is_executive:
              context['form_student'] = forms.StudentProfileForm(self.request.POST)
              context['form_professor'] = forms.ProfessorProfileForm(self.request.POST)
              context['form_executive'] = forms.ExecutiveProfileForm(self.request.POST)
  
          return super(AccountProfilesView, self).post(request, *args, **kwargs)
  
      def form_valid(self, form):
          context = self.get_context_data(form=form)
          user = self.request.user
          user = form.save()
          if user.is_student:
              student = context['form_student'].save(commit=False)
              student.user = user
              student.save()
          elif user.is_professor:
              professor = context['form_professor'].save(commit=False)
              professor.user = user
              professor.save()
          elif user.is_executive:
              executive = context['form_executive'].save(commit=False)
              executive.user = user
              executive.save()
          elif user.is_student and user.is_professor and user.is_executive:
              student = context['form_student'].save(commit=False)
              student.user = user
              student.save()
              professor = context['form_professor'].save(commit=False)
              professor.user = user
              professor.save()
              executive = context['form_executive'].save(commit=False)
              executive.user = user
              executive.save()
  
          return super(AccountProfilesView, self).form_valid(form)
  </code></pre>
  
  <p>And in my profile form template, I have the following small logic in which the render of the form to each profile of a separate way works, but when I ask if an user have the three profiles <code>is_student</code>, <code>is_professor</code> and <code>is_executive</code> such as is code section at the end of my template, and I going to profile page of this user, the three forms does not renderized:</p>
  
  <pre><code>&lt;form method="POST"&gt;
          {% csrf_token %}
          {% if userprofile.user.is_student %}
              {% bootstrap_form form_student %}
  
          {% elif userprofile.user.is_professor %}
              {% bootstrap_form form_professor %}
  
          {% elif userprofile.user.is_executive %}
              {% bootstrap_form form_executive %}
  
          {% elif userprofile.user.is_student and 
              userprofile.user.is_professor and 
              userprofile.user.is_executive %}
              {% bootstrap_form form_student %}
              {% bootstrap_form form_professor %}
              {% bootstrap_form form_executive %}
  
          {% endif %}    
          &lt;input type="submit" value="Save Changes" class="btn btn-default"&gt;
      &lt;/form&gt;
  </code></pre>
  
  <p>Why my three forms, is not possible show them in one form?</p>