Mojimi Mojimi - 18 days ago 6
Python Question

Django how to populate fields in 'trough' intermediate model when adding an object to a ManyToManyField?

I couldn't word it properly nor could I find it in the documentation, but how do I also add to the intermediate 'through' model of a

ManyToManyField
when adding new objects to it?

Note that its a recursive relationship, but I used
ManyToMany
as I was unsure if
OneToOne
supports a "through" model (the documentation does not specifies it)

Also
Person_Person
will be used regardless of the
curr_partner
field, adding objects like parents/child relationships to it (which have no field in
Person
)
(This was due to the confusion that ManyToManyField was an actual field in the output table in a SQL relational database)

(I realize that my model has some contextual/theoretical flaws, but let's abstract that for now)

For example

Models.py :

class Person(models.Model):
objectid = models.AutoField(primary_key=True)
name = models.CharField()
curr_partner = models.ManyToManyField(
self,
on_delete = models.CASCADE,
through = Person_Person, #This lets you define the model that will act as an intermadiary
symmetrical = False, #This needs to be set with recursive relationships
)

class Person_Person(models.Model):
person_1 = models.ForeignKey(Person, ondelete=models.CASCADE)
person_2 = models.ForeignKey(Person, ondelete=models.CASCADE)
relation = models.ChoiceField(
('P', 'Parent'),
('C', 'Child'),
('E', 'Engaged'),
('W', 'Widow'),
)


Query :

#Adding a married couple

father = Person(name = "John")
mother = Person(name = "Anna")

father.curr_partner.add( mother , through.relation = "Engaged") #???

#Adding a 'Child' relation

child = Person(name = "Billy")

#This makes sense??
p1 = Person_Person(person1 = father, person2 = child, relation = "Child")
p2 = Person_Person(person1 = mother, person2 = child, relation = "Child")

Answer

You create the relationships by saving instances of the relationship's model, like you (almost) did with the children. You'd have something like

father = Person(name = "John")
mother = Person(name = "Anna")

marriage = Person_Person.objects.create(person1=father, person2=mother, relation="E")

p1 = Person_Person.objects.create(person1=father, person2=child, relation="C")
p2 = Person_Person.objects.create(person1 = mother, person2 = child, relation="C")

BTW, your curr_partner attribute doesn't have an accurate name, since it actually denotes all of a person's relationships, not just marriage. Maybe you should rename it to relationships or kindred and have a property to get the person's partner:

@property
def curr_partner(self):
    try:
        return self.relationships.objects.get(relation='E')
    except Person_Person.DoesNotExist:
        # No marriage relationship
        return