chris Frisina
chris Frisina

Reputation: 19688

Pass a form object to other forms in the same page/view()

How do you reference a form object that was just created above in the form validation block of a view?

If you have a shared model, with two other optionally related models:

class Tree(models.Model):
  type= ...
class Picture(models.Model):
  camera = ...
  tree=models.ForeignKey(Tree)
class Lumber(models.Model):
  used_to_build = ...
  tree=models.ForeignKey(Tree)
  picture=models.ForeignKey(Picture, blank=True, null=True)
class Bird(models.Model):
  species = ...
  tree=models.ForeignKey(Tree)
  picture=models.ForeignKey(Picture, blank=True, null=True)

You can create a Bird, and Lumber in their own views, and of course reference a specific tree.

If you have a view, and you create a form that lets you create a picture of a tree, lumber, and a bird, and you want to pass the newly created Picture to the Lumber and BirdForm, since in this case, we know which Picture the lumber and Bird are in:

def treeView(request):   
  #Post
    pictureForm = PictureForm(instance=tree, prefix='treeForm')
    # This is what I am trying to figuere out
    # lumberForm = LumberForm(instance=tree, picture=pictureForm.object prefix='lumberForm')
    lumberForm = LumberForm(instance=tree, prefix='lumberForm')
    birdForm = BirdForm(instance=tree, prefix='birdForm')

How do you pass in the actual object created to the other forms that can optionally accept the related object? ie

                                                ▼ how do you pass in the form object from above?
 lumberForm = LumberForm(instance=tree, picture=pictureForm.object, prefix='lumberForm')

A relevant picture to help you smile :) [Some lumber from a tree with a(n absent) bird [1] Album: https://www.facebook.com/media/set/?set=a.10101895369321847.1073741831.36619363&type=1&l=70c30792e3

Upvotes: 1

Views: 41

Answers (1)

Vitor Freitas
Vitor Freitas

Reputation: 3610

I'm not 100% sure if I understood correctly the problem you are trying to solve, but I will try to provide a solution.

I'm considering the following assumptions:

  • You already have the Tree instance
  • The Picture, Lumber and Bird will be associated with the same Tree
  • The created Picture will be associated to the Lumber and the Bird created in the same view.

Basically what you are going to do is, wrap everything in the same database transaction and let it rain.

from django.db import transaction
from django.shortcuts import render, redirect

def treeView(request, pk):
    tree = Tree.objects.get(pk=pk)  # you tell me how you get your tree instance

    if request.method == 'POST':
        pictureForm = PictureForm(request.POST, prefix='treeForm')
        lumberForm = LumberForm(request.POST, prefix='lumberForm')
        birdForm = BirdForm(request.POST, prefix='birdForm')

        if pictureForm.is_valid() and lumberForm.is_valid() and birdForm.is_valid():
            with transaction.atomic():
                picture = pictureForm.save(commit=False)
                picture.tree = tree
                picture.save()

                lumber = lumberForm.save(commit=False)
                lumber.tree = tree
                lumber.picture = picture
                lumber.save()

                bird = birdForm.save(commit=False)
                bird.tree = tree
                bird.picture = picture
                bird.save()
            return redirect('success_view')
    else:
        pictureForm = PictureForm(prefix='treeForm')
        lumberForm = LumberForm(prefix='lumberForm')
        birdForm = BirdForm(prefix='birdForm')

    return render(request, 'tree_form.html', {
        'tree': tree,
        'pictureForm': pictureForm,
        'lumberForm': lumberForm,
        'birdForm': birdForm
    })

Upvotes: 1

Related Questions