11

My Models:

class End_User(models.Model):
    location = models.ForeignKey(Location) 
    first_name = models.CharField(max_length=70, blank=True, null=True)
    email_address = models.CharField(max_length=70, blank=True, null=True)

class Phone_Client(models.Model):
    end_user = models.ManyToManyField(End_User)
...
    extensions = models.CharField(max_length=20)

class Line(models.Model):
    phone_client = models.ManyToManyField(Phone_Client, through='Phone_Line' )
    ....
    voicemail = models.BooleanField(default=False)  

class Phone_Line(models.Model):
    phone_client = models.ForeignKey(Phone_Client)
    line = models.ForeignKey(Line)
    line_index = models.IntegerField()

So basically One end user can have many phones, a phone can have many Lines, related through Phone_line.

My page need to have all these objects editable and new instances created runtime for Phone_Clients and Line all in the same page. Currently I am creating a simple End_User model form and modelformset_factory objects for Phone_Client and Lines. Since a phone can have many lines, each phone form in the phone_formset can have a line formset object. I am currently doing something like this

end_user = End_User.objects.get(pk=user_id)
user_form = End_UserForm(instance=end_user)

Phone_ClientFormSet = modelformset_factory(Phone_Client,form=PartialPhone_ClientForm,  extra=0, can_delete=True)

phone_clients_formset = Phone_ClientFormSet(queryset=end_user.phone_client_set.all(), prefix='phone_client')

all_lines = modelformset_factory(Line, form=PartialLineForm, extra=0, can_delete=True)

phone_clients = end_user.phone_client_set.all()

client_lines_formsets = {}
for phone in phone_clients:
    client_lines_formsets[phone.id] = all_lines(queryset=phone.line_set.all(), prefix='phone_client_'+str(phone.id))

I am using this list to display lines belonging to a phone_client in the template using formsets.

I have the following question, on the models

  1. Can I use inline_formset factory to handle many to many relation containing a through class? if so how do I do that for the Phone_Client, Line and Phone_Line through relation?

  2. I need to display the line_index for a given phone, line combination, how do I do that in template? I have looked at
    How do I access the properties of a many-to-many "through" table from a django template? I do not want to only display, but bind the value to the phone, line combination if possible in the line or phone formset, such that if user changes the index, I can save that in the data base while posting the formset data.

I am new to django so any help is really appreciated. Thanks!!

Community
  • 1
  • 1
akotian
  • 3,885
  • 1
  • 33
  • 44

1 Answers1

17

As you're probably aware, you can't edit many-to-many relationships with inline formsets. You can, however, edit the through model. So for your inline formset, you just need to set the model to the through model, e.g.:

inlineformset_factory(Phone_Client, Line.phone_client.through)

line_index will actually be a visible field on the inline form, so you really don't have to do anything. If someone changes the index, it'll be saved when the inline forms are saved, just like the rest of the fields.

Chris Pratt
  • 232,153
  • 36
  • 385
  • 444
  • I tried this out and it works for me. However one question, I would have to separately handle the Line formset and the the above inline formset right?? – akotian Jun 13 '12 at 21:29
  • I mean a page can have multiple phone, which can have multiple lines, so I handle this logic in template. Similarly I would have to use templates right to display line_index next to the lines? – akotian Jun 13 '12 at 21:40
  • You can't have inlines within inlines. You can edit phones inline with the end user, and then edit lines inline with the phone on another view. – Chris Pratt Jun 13 '12 at 21:52