1

In Django, I have the following models.

class Genus(models.Model):
    genus_name=models.CharField(max_length=30)
    ...

class HostSpecies(models.Model):
    species_genus=models.ForeignKey(Genus)
    ...

class HostStrain(models.Model):
    strain_species=models.ForeignKey(HostSpecies)
    strain_name=models.CharField(max_length=50)
    ...

Now I'm trying to use Django REST Framework to serialize the the HostStrain model as follows.

class HostStrainSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = HostStrain
        fields = ('strain_species__species_genus','strain_species','strain_name')

But the standard double-underscore notation in Django doesn't seem to work here, since I get the error:

Field name strain_species__species_genus is not valid for model HostStrain.

I'd like to include a link to (or at least the __unicode__ from) the Genus model in my HostStrain serialization.

So how do I follow multi-level relationships in Django REST Framework's serialization?

1 Answer 1

2

There are a few ways you can do this.

You can include other serializers on your HostStrainSerializer

class GenusSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Genus
        fields = ('genus_name')

class HostSpeciesSerializer(serializers.HyperlinkedModelSerializer):
    species_genus = GenusSerializer()

    class Meta:
        model = HostSpecies
        fields = ('species_genus')

class HostStrainSerializer(serializers.HyperlinkedModelSerializer):
    strain_species = HostSpeciesSerializer()

    class Meta:
        model = HostStrain
        fields = ('strain_species','strain_name')

This way your serializer will output something like this:

{
    "strain_name": "...",
    "strain_species": {
        "species_genus": {
            "genus_name": "..."
        }
    }
}

Another way you can do this is to create fields on your HostStrainSerializer that gets the information from the other models.

class HostStrainSerializer(serializers.HyperlinkedModelSerializer):
    strain_species = HostSpeciesSerializer()
    species_genus = serializers.ReadOnlyField(source='strain_species.species_genus.genus_name')

    class Meta:
        model = HostStrain
        fields = ('species_genus', 'strain_species','strain_name')

You can also use a SerializerMethodField

class HostStrainSerializer(serializers.HyperlinkedModelSerializer):
    strain_species = HostSpeciesSerializer()
    species_genus = serializers.SerializerMethodField()

    def get_species_genus(self, instance):
        return instance.strain_species.species_genus.genus_name

    class Meta:
        model = HostStrain
        fields = ('species_genus', 'strain_species','strain_name')
Sign up to request clarification or add additional context in comments.

1 Comment

The second method is basically what I was after, and just totally missed the source parameter in the docs. Thanks!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.