Как применить преобразование к полю при сериализации?

#python #django #django-rest-framework #geodjango

#python #django #django-rest-framework #geodjango

Вопрос:

Как в Django применить пользовательское преобразование при сериализации поля?

Например, у меня есть модель, в которой есть geometry поле, которое хранится в определенной системе координат. Теперь, для этого одного сериализатора, я хотел бы выполнить преобразование, которое преобразует координаты в другую систему координат. Как это делается?

Сериализатор в настоящее время выглядит следующим образом:

 class LinkWithGeometrySerializer(serializers.ModelSerializer):
    class Meta:
        model = Link
        fields = ['link_type',
                  'geometry',
                  ]
 

Это поле, geometry к которому должно быть применено преобразование.

Комментарии:

1. django-rest-framework.org/api-guide/fields/#custom-fields

Ответ №1:

Как указал Иклинац, вы можете использовать пользовательское поле, но это окупается только тогда, когда вы можете использовать его повторно.

Есть два других распространенных подхода:

Держите его на уровне сериализатора:

 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)
 

На уровне модели (заставить базу данных выполнить преобразование):

на ваш взгляд:

 from django.contrib.gis.db.models.functions import Transform
TARGET_SRID = 4326
class LinkView(RetrieveAPIVIew):
    queryset = Link.objects.annotate(transformed=Transform("geometry", TARGET_SRID))
    ...
 

или (srid передается как компонент пути в 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"])
 

сериализатор

 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