openwisp / django-rest-framework-gis

Geographic add-ons for Django REST Framework. Maintained by the OpenWISP Project.
http://openwisp.org
MIT License
1.08k stars 199 forks source link

Allow geo_field to be an annotated field #250

Open henhuy opened 3 years ago

henhuy commented 3 years ago

I have a model with a geom (srid=3035) and I want to serialize it as geom (srid=4326). Did not found a solution to do this with django-restframework-gis? My approach was:

from django.contrib.gis.db.models.functions import Transform

class TransformManager(models.Manager):
    def get_queryset(self):
        return super().get_queryset().annotate(geom_4326=Transform("geom", 4326))

class State(models.Model):
    id = models.BigIntegerField(primary_key=True)
    name = models.CharField(max_length=60)
    geom = models.MultiPolygonField(srid=3035)

    objects = TransformManager()

class StatesSerializer(GeoFeatureModelSerializer):
    class Meta:
        model = State
        geo_field = "geom_4326"
        fields = [
            "id",
            "name",
            "geom_4326"
        ]

class StatesListAPIView(ListAPIView):
    queryset = State.objects.all()
    serializer_class = StatesSerializer
    lookup_field = 'id'

but this gives me: django.core.exceptions.ImproperlyConfigured: Field namegeom_4326is not valid for modelState.

Also found this: https://stackoverflow.com/questions/22449406/how-to-transform-geometry-in-django-rest-framework-gis/22537247#22537247 But couldn't get it to work... (see my comment on that answer)

Any help? thx

StefanBrand commented 3 years ago

Try this (using GeometrySerializerMethodField):

class InSituCommentSerializer(GeoFeatureModelSerializer):
    geometry_4326 = GeometrySerializerMethodField()

    def get_geometry_4326(self, state) -> Polygon:
        return state.geom.transform(4326, clone=True)

    class Meta:
        model = Instance
        geo_field = "geometry_4326"
        fields = ("name", )
a-gorski-aic commented 2 years ago

Other solution that is cleaner in my opinion because it uses db for transformation:


class StatesSerializer(GeoFeatureModelSerializer):
    geom_4326 = GeometryField()

    class Meta:
        model = State
        geo_field = "geom_4326"
        fields = [
            "id",
            "name",
            "geom_4326"
        ]