How can I handle multiple forms on one page using the DRY method

94 views Asked by At

I have a total of 10 forms I need to display. I am using a DetailView to display them and a CreateView to handle their logic. So far my views.py looks like this:

from .forms import (
    WeightRepsModelForm as wr_form,
    WeightDistanceModelForm as wd_form,
    WeightTimeModelForm as wt_form,
    RepsDistanceModelForm as rd_form,
    RepsTimeModelForm as rt_form,
    DistanceTimeModelForm as dt_form,
    WeightModelForm as w_form,
    RepsModelForm as r_form,
    DistanceModelForm as d_form,
    TimeModelForm as t_form,
)

class ExerciseDetailView(DetailView):
    model = Exercise
    template_name = 'workouts/types.html'

    def get_context_data(self, **kwargs):
        context = super(ExerciseDetailView, self).get_context_data(**kwargs)
        context['wr_form'] = wr_form
        context['wd_form'] = wd_form
        context['wt_form'] = wt_form
        context['rd_form'] = rd_form
        context['rt_form'] = rt_form
        context['dt_form'] = dt_form
        context['w_form'] = w_form
        context['r_form'] = r_form
        context['d_form'] = d_form
        context['t_form'] = t_form
        return context

class WeightRepFormView(CreateView):
    form_class = wr_form

    def form_valid(self, form):
        form.instance.exercise_id = self.kwargs['pk']
        return super().form_valid(form)

    def get_success_url(self):
        return reverse('workouts:exercise_detail', kwargs={'pk': self.kwargs['pk']})

This works fine for the first form but I would need to create 10 near identical CreateViews in order to continue with this method. Is anyone able to recommend a more efficient way of doing this?

1

There are 1 answers

0
Roohollah Mozaffari On

First it would be easier for you to do the both job showing the forms and saving them using one class. even if you want to save all the forms at the same time(which I think you want) you can not do that with 10 different view with one buttons. you first part of showing the forms are ok. in ExerciseDetailView define a post method to handle the post request . then in that def post() :

def post( self, request):
    wr = wr_form(request.POST)
    if wr.is_valid():
        #save the the instance and change it the way you want 
    wd = wd_form(request.POST)
    if wd.is_valid():
        #save the instance and change it the way you want 
      .
      .
      .

and after 10th form redirect to a page. Remember if your user want to input data more than one form and to save them, you cant do that with more than one function or class .note that in you template you should do this:

      <form method="POST">
      {% csrf_token %}
      <fieldset class="form-group">
          <legend class="border-bottom mb-4">complete the form(s)</legend>
          {{ wr_form|crispy }}
          {{ wd_form|crispy }}
                 .
                 .
                 .
           # put all the 10 form like this 
      </fieldset>
      <div class="form-group">
          <button class="btn btn-outline-info" type="submit">Save</button>
         # it is bootstrap but the form are every where like this 

by this the user pass all the forms and their data with one button .(one csrf_token ) if you was thinking about sth else let me know. (Nothing personal but if you are showing 10 different in one single template it sounds like you have made a mistake in your and analysis.)