Rich Ross
Rich Ross

Reputation: 705

Django multiple forms on one view

I have a Django template that has data from a few different model types combining to make it. A dashboard if you will. And each of those has an edit form.

Is it best to process all those forms in one view as they are posted back to the same place and differentiating between them by a unique field like below?

Or if having lots of different dedicated avenues is the way forward? Thanks for any guidance

class ProjectDetail(DetailView):

template_name = 'project/view.html'

def get_object(self):
    try:
        return Project.objects.filter(brief__slug=self.kwargs['slug']).filter(team=get_user_team(self.request)).first()
        # add loop to allow multiple teams to work on the same brief (project)
    except Exception as e:
        project_error = '%s (%s)' % (e.message, type(e))
        messages.error(self.request, 'OH NO! %s' % project_error)
        return redirect('home')

def get_context_data(self, **kwargs):
    project = self.get_object()
    context = dict()
    context['project'] = project
    context['milestone_form'] = MilestoneForm(initial={'project': project})
    context['view'] = self
    return context

def post(self, request, *args, **kwargs):
    # get the context for the page
    context = self.get_context_data()
    try:
        # switch for each of the form types on the team profile page (shown if member)
        if 'milestone_form_submit' in request.POST:
            project=self.get_object()
            # set date arbitrarily to half way to brief deadline
            brief = Brief.objects.get(project=project)
            last_milestone = self.milestones().last()
            milestone_del_date = last_milestone.del_date + timedelta(days=7)

            new_milestone = Milestone(
                                project=project,
                                title_text=request.POST.get('title_text'),
                                del_date=milestone_del_date,
                                )
            try:
                new_milestone.save()
                messages.success(self.request, "Excellent! New delivery popped on the bottom of the list")
            except Exception as e:
                # pass the erroring form back in the context if not
                form = MilestoneForm(request.POST)
                context['milestone_form'] = form
                messages.error(self.request, "OH NO! Deadline didn't save. Be a sport and check what you entered")

        elif 'milestone-edit-date-form-submit' in request.POST:
            # get object from db
            milestone = Milestone.objects.get(pk=request.POST['id'])
            # update del_date field sent
            milestone.del_date = request.POST['del_date']
            # save back to db
            milestone.save()
            messages.success(self.request, "Updated that delivery right there!")

        elif ...

    except Exception as e:
        messages.error(self.request, "OH NO! Deadline didn't save. Be a sport and check what you entered")
    return render(request, self.template_name, context)

Upvotes: 2

Views: 7218

Answers (1)

Adilet Maratov
Adilet Maratov

Reputation: 1382

You can use mixins in order to solve your problem.

Example from the gist https://gist.github.com/michelts/1029336

class MultipleFormsMixin(FormMixin):
    """
    A mixin that provides a way to show and handle several forms in a
    request.
    """
    form_classes = {} # set the form classes as a mapping

    def get_form_classes(self):
        return self.form_classes

    def get_forms(self, form_classes):
        return dict([(key, klass(**self.get_form_kwargs())) \
            for key, klass in form_classes.items()])

    def forms_valid(self, forms):
        return super(MultipleFormsMixin, self).form_valid(forms)

    def forms_invalid(self, forms):
        return self.render_to_response(self.get_context_data(forms=forms))

As you can see, when you inherit from this class, you can handle multiple forms simultaneously. Look at the gist's code and adapt it to your problem.

Look at this answer

Upvotes: 6

Related Questions