In Django, how does one apply a custom transformation while serializing a field?
For instance, I have a model which has a geometry
field, which is stored in a specific coordinate system. Now, for this one serializer, I'd like to perform a conversion that converts the coordinates to another coordinate system. How is that done?
The serializer currently looks like this:
class LinkWithGeometrySerializer(serializers.ModelSerializer):
class Meta:
model = Link
fields = ['link_type',
'geometry',
]
The geometry
is the field that should have a transformation applied to it.
As Iklinac pointed out, you can use a custom field, but that only pays off when you can reuse it.
There's two other common approaches:
Keep it at serializer level:
class LinkWithGeometrySerializer(serializers.ModelSerializer):
geometry = serializers.SerializerMethodField()
class Meta:
model = Link
fields = ['link_type', 'geometry',]
@staticmethod
def get_geometry(obj: Link):
# for example obtain srid from context, by passing it in via view or hardcode
return obj.geometry.transform(srid=your_srid)
At the model level (make the database do the transformation):
in your view:
from django.contrib.gis.db.models.functions import Transform
TARGET_SRID = 4326
class LinkView(RetrieveAPIVIew):
queryset = Link.objects.annotate(transformed=Transform("geometry", TARGET_SRID))
...
or (srid passed as path component in url):
from django.contrib.gis.db.models.functions import Transform
class LinkView(RetrieveAPIVIew):
def get_queryset(self):
return Link.objects.annotate(transformed=Transform("geometry", self.kwargs["srid"])
serializer
class LinkWithGeometrySerializer(serializers.ModelSerializer):
geometry = serializers.GeometryField(source='transformed') # [1]
class Meta:
model = Link
fields = ['link_type', 'geometry',]
[1] https://github.com/openwisp/django-rest-framework-gis/blob/master/rest_framework_gis/fields.py#L13