Search code examples
pythondjangodjango-rest-frameworkmany-to-many

Django Rest Framework with Self-referencing many-to-many through unable to get the through model


I am trying to get the relations and the relationship for a particular instance. I need to get both the related objects id and the relationship information.

My models are based off of relationships from http://charlesleifer.com/blog/self-referencing-many-many-through/

Django 1.8.3 and Django Rest Framework 3.3.3

models.py

class Person(models.Model):
    name = models.CharField(max_length=100)
    relationships = models.ManyToManyField('self', through='Relationship',
                                           symmetrical=False,
                                           related_name='related_to')

class RelationshipType(models.Model):
    name = models.CharField(max_length=255)


class Relationship(models.Model):
    from_person = models.ForeignKey(Person, related_name='from_people')
    to_person = models.ForeignKey(Person, related_name='to_people')
    relationship_type = models.ForeignKey(RelationshipType)

serializers.py

class RelationshipTypeSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.RelationshipType


class RelationshipSerializer(serializers.ModelSerializer):
    relationship_type = RelationshipTypeSerializer()
    to_person_id = serializers.ReadOnlyField(source='to_person.id')
    to_person_name = serializers.ReadOnlyField(source='to_person.name')

    class Meta:
        model = models.Relationship
        fields = (
            'id',
            'relationship_type',
            'to_person_id',
            'to_person_name',
        )


class PersonSerializer(serializers.ModelSerializer):
    annotated_relationships = RelationshipSerializer(source='relationships', many=True)

    class Meta:
        model = models.Person
        fields = (
            "id",
            "name",
            'annotated_relationships'
        )

I am currently getting something like this:

{
    "id": 88,
    "name": "Person 88",
    "annotated_relationships": [
        {
            "id": 128
        },
        {
            "id": 130
        }
    ]
}

What I want looks like this, though the format doesn't need to be this way as long as I can get the relationship information:

{
    "id": 88,
    "name": "Person 88",
    "annotated_relationships": [
        {
            "id": 128,
            "relationship_type":
                {
                    "name": "friend",
                },
            "to_person_id": 34,
            "to_person_name": "Jeremy",

        },
        {
            "id": 130,
            "relationship_type":
                {
                    "name": "enemy",
                },
            "to_person_id": 73,
            "to_person_name": "Trisha",
        }
    ]
}

Solution

  • You can define a method

    def get_relations(self): 
        return models.Relationship.objects.get(from_person=self) 
    

    Then do

    annotated_relationships = RelationshipSerializer(source=get_relations,many=True)