Friday, January 29, 2021

How to programmatically set the model when using Django CreateView?

I am trying to programmatically set the model for a Django class-based view that inherits from CreateView and displays a form for creating a 'member' object. My problem is that  my template is not displaying the form itself. Note that I override the 'get' method to determine what model the view should use. The template page renders and I see the submit button but when I view the page's source code, the form is missing. Here's my code:

    # urls.py
    path('profile/create/', views.ProfileCreate.as_view(), name='profile-create'),

    # views.py
    class ProfileCreate(CreateView):
        model = None
        template_name = None

        def get(self, request, *args, **kwargs):
            member = Member.objects.get(user=request.user)
            if member.is_couple:
                self.model = ProfileCouple
                self.template_name = 'account/profile_couple_create.html'
                self.fields = ['person1_name', 'person2_name',
                               'person1_dob', 'person2_dob']
            else:
                self.model = ProfileSingle
                self.template_name = 'account/profile_single_create.html'
                self.fields = ['person1_name', 'person1_dob']

            context = {}
            return render(request, self.template_name, context)

    # models.py
    class ProfileSingle(models.Model):
        user = models.OneToOneField(User, on_delete=models.CASCADE, null=True)
        person1_name = models.CharField(_("Name"), max_length=50)
        person1_dob = models.DateField()

        def __str__(self):
            return self.user.username

    class ProfileCouple(models.Model):
        user = models.OneToOneField(User, on_delete=models.CASCADE, null=True)
        person1_name = models.CharField(_("Name 1"), max_length=50)
        person1_dob = models.DateField()
        person2_name = models.CharField(_("Name 2"), max_length=50)
        person2_dob = models.DateField()

        def __str__(self):
            return self.user.username

    # forms.py
    class CreateSingleProfileForm(forms.ModelForm):
        class Meta:
            model = ProfileSingle
            fields = ('user', 'person1_name', 'person1_dob')
            labels = {'user': _('Username'), 'person1_name': _(
                'Person 1 Name'), 'person1_dob': _('Person 1 DOB')}
    
    class CreateCoupleProfileForm(forms.ModelForm):
        class Meta:
            model = ProfileCouple
            ...

    # profile_single_create.html
    <div class="container mt-4">
      <h1>Create Your Profile</h1>
      <form method="post">{% csrf_token %}
          {{ form.as_p }}
          <input type="submit" value="Save">
      </form>
    </div>

    # profile_couple_create.html
    (Code similar to single template)

I know that with CBVs, Django will build the form for me.  But there will be times when I need to customize the form as I do here. What am I missing?

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/6d394628-6132-4927-8324-466347c8c427n%40googlegroups.com.

No comments:

Post a Comment