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 (This was due to the confusion that ManyToManyField was an actual field in the output table in a SQL relational database)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
)
(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")
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