0

The Quetion

Hello. I'm trying to figure out the best way to use one form to create one parent object and then create 0-n sub objects. I'm assuming ModelForms are what I need to do, but I'm having a hard time understanding how to structure the template and view. Would someone be willing to explain how to create n number of sub objects?

The Research

I've read several other articles and posts relating to this:

To name a few.

The Details

I have two models like so:

// models.py

class DataItem(models.Model): name = models.CharField(max_length=255) date_created = models.DateTimeField(auto_now_add=True) date_last_updated = models.DateTimeField(auto_now_add=True) owner = models.ForeignKey(User, blank=False) def __unicode__(self): return self.name class DataItemSet(models.Model): item = models.ForeignKey(DataItem, blank=False) type_ind = models.IntegerField() 

And I've created two ModelForms to correspond:

// forms.py

class CreateDataItemForm(forms.ModelForm): class Meta: model = DataItem exclude = ('owner',) def save(self, user, commit=True): item = super(CreateDataItemForm,self).save(commit=False) item.owner = user if commit: item.save() return item class CreateDataItemSetForm(forms.ModelForm): class Meta: model = DataItemSet exclude = ('item',) def save(self, parent, commit=True): set = super(CreateDataItemSetForm,self).save(commit=False) set.item = parent if commit: set.save() return set 

And in my view, I'm trying to have one form submit the creation of a new DataItem and 1-n DataItemSets which are owned by the DataItem. Here is an example of the output of the form:

Example create data item form

And the template:

<form action="." method="post"> {% csrf_token %} <table> {{ create_form.as_table }} </table> <table> <tr> <th>What to track:</th> <td> <select> <option value="1">Number</option> <option value="2">Currency ($)</option> <option value="3">Date</option> <option value="4">Day</option> <option value="5">Time</option> </select> </td> <td> </td> </tr> <tr> <th>What to track:</th> <td> <select> <option value="1">Number</option> <option value="2">Currency ($)</option> <option value="3">Date</option> <option value="4">Day</option> <option value="5">Time</option> </select> </td> <td> <button type="button">+</button> </td> </tr> </table> <p> <button type="submit">Create</button> </p> </form> 

And lastly, the view:

// views.py

@login_required @csrf_protect def create_data_item(request): create_form = CreateDataItemForm() c = {'create_form':create_form} c.update(csrf(request)) if request.method == 'POST': data = request.POST.copy() form = CreateDataItemForm(data, instance=DataItem()) item_sets = [CreateDataItemSetForm(request.POST, prefix=str(x), instance=DataItemSet()) for x in range(0,9)] if form.is_valid(): # create new data item new_item = form.save(request.user) #create new set of stuff to track for item_set in item_sets: new_item_set = item_set.save(new_item) # return to the add entry page return redirect('/add') else: return render_to_response('internal/create_data_item.html',c) 

I'm missing how to allow for dynamic extraction of 0-n DataItemSets from the form. I can't figure it out with ModelForm.

Thanks for any help!

1 Answer 1

2

This is what model formsets - specifically, inline formsets - are for.

Sign up to request clarification or add additional context in comments.

2 Comments

What I'm not understanding is what the "+" button should do to dynamically insert a new drop down list (refer to image in original post). I can't find any documentation when research FormSets/InlineForms. Can you expand on that?
I was able to find this, which really helped me! Thanks for your help. docs.djangoproject.com/en/dev/topics/forms/formsets/…

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.