Houman
Houman

Reputation: 66320

Form within a form in Django?

I have been looking at the documentation and thought maybe inline-formsets would be the answer. But I am not entirely sure.

Usually whenever you create a ModelForm it is bound to the related Model only. But what if you wanted to edit two models within a form?

In a nutshell, when editing the class conversation, and selecting a Deal class from the dropdown, I would like to be able to change the status of the selected deal class as well (but not the deal_name). All within the same form. Does Django allow that?

class Deal(models.Model):    
    deal_name           = models.CharField()
    status              = models.ForeignKey(DealStatus)

class Conversation(models.Model):
    subject             = models.CharField()
    deal                = models.ForeignKey(Deal, blank=True, null=True)

Update:

The reason I wasn't sure if inline-formssets are the answer is the following behaviour:

View:

call = get_object_or_404(contact.conversation_set.all(), pk=call_id)
ConversationFormSet = inlineformset_factory(Deal, Conversation)
fset = ConversationFormSet(instance=call)    
variables = RequestContext(request, {'formset':fset})
return render_to_response('conversation.html', variables)

Template

{{ formset }}  

The result I am getting is not what I expected. I am getting three forms of Conversation class, where the first one is filled out (due editing and passing in the isntance). However the Deal DropDown menu is not listed at all. Why?

Upvotes: 3

Views: 6858

Answers (2)

Frank Fang
Frank Fang

Reputation: 149

Another approach is to use signal like this:

def update_deal_status(sender, instance, created, **kwargs):
    if created:
        deal = Deal.objects.get(id__exact=instance.deal_id)
        deal.status  = instance.status 
        deal.save()

signals.post_save.connect(update_deal_status, sender=Conversation)

Upvotes: 2

Houman
Houman

Reputation: 66320

I found the solution and hope this will help someone else with the same problem in the future. I ended up redesigning my models.

I simply added the status also to my Conversation model.

class Conversation(models.Model):
    subject             = models.CharField()
    deal                = models.ForeignKey(Deal, blank=True, null=True)
    status              = models.ForeignKey(DealStatus)

In the view I added a custom save like this:

if form.is_valid():            
            call = form.save(commit=False)
            deal =  get_object_or_404(Deal.objects.all(), pk=call.deal.id)
            deal.status = call.status
            deal.save()
            call.save()  

That works nicely.

Upvotes: 2

Related Questions