I have 2 classes, Country and Coordinates. When making an API call to the Country table, I would like the API (using DRF) to return the related Coordinate information as well.
By default, the following is understandably returned (localhost:8000/api/country/):
{
"id": 1,
"name": "TestCountry",
"coordinates": 1
}
The problem is that after implementing select_related in my views.py file, and modifying the CountrySerializer as well, the output remains exactly the same. I had expected something like:
{
"id": 1,
"name": "TestCountry",
"coordinates": {
"longitude": 123,
"latitude": 456,
}
}
Or even this would suffice:
{
"id": 1,
"name": "TestCountry",
"longitude": 123,
"latitude": 456,
}
And here are the relevant code in models, views, and serializer files.
class Coordinates(models.Model):
longitude = models.DecimalField()
latitude = models.DecimalField()
class Country(models.Model):
name = models.CharField()
coordinatesID = models.ForeignKey(Coordinates, on_delete=models.SET_NULL, verbose_name="Coordinates", db_column="CoordinatesID", blank=True, null=True, related_name="coordinates")
class CountryViewSet(viewsets.ReadOnlyModelViewSet):
queryset = Country.objects.select_related('coordinatesID').all()
serializer_class = CountrySerializer
class CountrySerializer(DynamicFieldModelSerializer):
longitude = serializers.ReadOnlyField(source='coordinates.longitude')
latitude = serializers.ReadOnlyField(source='coordinates.latitude')
class Meta:
model = Country
fields = '__all__'
Additionally, in the Country table, I specified the related_name="coordinates", however select_related does not recognize this option, and I still have to use "coordinatesID" to reference the coordinate table. Is this a bug or related to incorrect implementation?
Note that related_name
is used to access the relationship in reverse from the Coordinates
model side to Country
side not the opposite.
so in the select_related
you can use all fields and relationships that are defined on the Model itself, so for Country
model if you defined coordinates relationship as coordinatesID
you will need to do like this
queryset = Country.objects.select_related('coordinatesID').all()
and to use in the serializer
longitude = serializers.ReadOnlyField(source='coordinatesID.longitude')
latitude = serializers.ReadOnlyField(source='coordinatesID.latitude')
also using a field name like coordinatesID
is not great naming convention in django since you would have a property like coordinatesID.id
which is not very clean.
https://docs.djangoproject.com/en/3.2/topics/db/examples/many_to_one/