0

I have two model classes, Person and Relationship as follows with fields omitted for brevity:

class Person(models.Model):
    first_name = models.CharField(max_length=32, null=True)
    .
    .
    .
    relationship = models.ManyToManyField('Relationship', related_name='relative')


class Relationship(models.Model):
    person = models.ForeignKey('Person', related_name='relative', null=True)

Let's say Person A is a father and Person B is a daughter. I would have create them as follows:

personA = Person()
personA.first_name = "Father"
personA.save()

personB = Person()
personB.first_name = "Daughter"
personB.save()

Then the relationships between them:

daughterRelationship = Relationship()
daughterRelationship.person = personB
daughterRelationship.save()
personA.relationship.add(daughterRelationship)

fatherRelationship = Relationship()
fatherRelationship.person = personA
fatherRelationship.save()
personB.relationship.add(fatherRelationship)

Now, based on my models (maybe related_name='relative' is causing the issue), but I can't seem to figure out my reverse lookup name.

I've tried these, but to no avail:

relationship = Relationship.objects.get(id=1)
personA = relationship.person
personB = relationship.relative_set.all().get() # Relationship does not have attribute 'relative_set'
personB = relationship.person_set.all().get() # Relationship does not have attribute 'person_set'
personB = relationship.relationship_set.all().get() # Relationship does not have attribute 'relationship_set'
personB = relationship.personrelationship_set.all().get() # Relationship does not have attribute 'personrelationship_set'
personB = relationship.personrealtive_set.all().get() # Relationship does not have attribute 'personrelative_set'

I can't seem to get it, can anybody else see what's going on, or any suggestions? Thanks.

Furbeenator
  • 8,106
  • 4
  • 46
  • 54

2 Answers2

1

Got it, the related_name='relative' was creating the reverse lookup as relative instead of relative_set.

relationship = Relationship.objects.get(id=1)
personA = relationship.person
personB = relationship.relative.all().get()
Furbeenator
  • 8,106
  • 4
  • 46
  • 54
1

I think this situation is better suited to a recursive relationship of Person to itself through Relationship.

acjay
  • 34,571
  • 6
  • 57
  • 100
  • Thanks for the response, ac. This would be perfect, except that I left out another field in the relationship class, which is relationship type. I want to know not only are they related, but how (daughter, father, sister, etc.). For that reason, I need to abstract it out to a separate class. – Furbeenator Dec 13 '12 at 16:26
  • That's fine, you can leave the relationship type there. That's what the `through` argument is for (see https://docs.djangoproject.com/en/dev/topics/db/models/#extra-fields-on-many-to-many-relationships). Or perhaps the most normalized thing you could do is make RelationshipType another model and put a foreign key from Relationship to it. – acjay Dec 13 '12 at 17:43
  • Oh nice, just curious, what is the benefit of using the through for M2M to itself (person to person) as opposed to M2M to Relationship class? Is this performance or just for clean code reuse? The reason I ask, is I still need to create the Relationship class with FK field to RelationshipType class either way. It's just a Person M2M to Person through Relationship or Person M2M to Relationship directly. Just curios why would it be better? – Furbeenator Dec 13 '12 at 23:14
  • Practically speaking, there's probably not a whole lot of difference. It's just a bit more explicit to think of `Relationship` as a relation with properties rather than an entity in itself, and you might get a bit more sugar out of the ORM. Like you could query all related people to a `Person` directly through an instance (i.e. `personA.relatives.all()`, instead of going through `Relationship`. I think where it would come in to play is by better facilitating joins from both sides of the relation, but I can't really think of a concrete slam dunk case for it. – acjay Dec 13 '12 at 23:37
  • That's interesting. I will definitely switch to using that method. I like using the Person to get relatives rather than getting their relationships. Thanks for the suggestion and explanation! – Furbeenator Dec 13 '12 at 23:53