GeoDjango:距离对象不可序列化

GeoDjango:距离对象不可序列化,django,serialization,geodjango,django-annotate,Django,Serialization,Geodjango,Django Annotate,我只是在学吉奥舞。我可以从一个点上找出所有地方的距离。但是当我对带注释的距离字段使用.values方法时,我得到 TypeError:Distance类型的对象不可JSON序列化 这是我的代码片段 #models.py import uuid from django.contrib.gis.db import models from django.contrib.gis.db.models.functions import Distance from django.contrib.gis.geo

我只是在学吉奥舞。我可以从一个点上找出所有地方的距离。但是当我对带注释的
距离
字段使用
.values
方法时,我得到

TypeError:Distance类型的对象不可JSON序列化

这是我的代码片段

#models.py
import uuid
from django.contrib.gis.db import models
from django.contrib.gis.db.models.functions import Distance
from django.contrib.gis.geos import Point
class PlaceManager(models.GeoManager):
    def get_queryset(self):
        qs = super(PlaceManager, self).get_queryset()
        qs = qs.annotate(
        latitude=models.ExpressionWrapper(models.Func('position', function='ST_X'), output_field=models.FloatField()),
        longitude=models.ExpressionWrapper(models.Func('position', function='ST_Y'), output_field=models.FloatField()),
    )
    return qs.distinct()

    def nearby_places(self, lat, lng):
        p = Point(lat, lng, srid=4326)
        qs = self.get_queryset()
        qs = qs.annotate(
            distance=Distance('position', p)
        )
        return qs.order_by('distance').distinct()


class Place(models.Model):
    id = models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, db_index=True)
    position = models.PointField()
    address = models.TextField(default=None, null=True, blank=True)
    objects = PlaceManager()

    def __str__(self):
        return '{},{}'.format(self.position.x, self.position.y)
现在我的代码片段是这样的

from rest_framework.views import APIView
from rest_framework import status
from rest_framework.response import Response

class NearbyPlaces(APIView):
    def get(self, request):
        p = Place.objects.nearby_places(30.45, -90.43)
        p = p.values('distance', 'address', 'latitude', 'longitude')
        return Response(p, status=status.HTTP_200_OK)
<GeoQuerySet [{'distance': Distance(m=7596021.71574835), 'address': 'New York City, New York','latitude': 13.4586, 'longitude': 45.6789}]>
p
的值如下

from rest_framework.views import APIView
from rest_framework import status
from rest_framework.response import Response

class NearbyPlaces(APIView):
    def get(self, request):
        p = Place.objects.nearby_places(30.45, -90.43)
        p = p.values('distance', 'address', 'latitude', 'longitude')
        return Response(p, status=status.HTTP_200_OK)
<GeoQuerySet [{'distance': Distance(m=7596021.71574835), 'address': 'New York City, New York','latitude': 13.4586, 'longitude': 45.6789}]>

所以我在这里需要的是
“距离”:7596021.71574835
而不是
“距离”:距离(m=7596021.71574835)

有什么帮助吗?提前谢谢。

刚刚找到了一种方法。 必须在rest框架中创建一个渲染器类,并处理其中的
距离
对象。代码片段如下所示

编码器

from rest_framework.utils.encoders import JSONEncoder
from django.contrib.gis.measure import Distance


class CustomJsonEncoderWithDistance(JSONEncoder):
    def default(self, obj):
        if isinstance(obj, Distance):
            print(obj)
            return obj.m
        return super(CustomJsonEncoderWithDistance, self).default(obj)
.py

from rest_framework.renderers import JSONRenderer
from .encoders import CustomJsonEncoderWithDistance


class CustomJsonRenderer(JSONRenderer):
     encoder_class = CustomJsonEncoderWithDistance
设置.py

...
REST_FRAMEWORK = {
    'DEFAULT_RENDERER_CLASSES': (
        'app.renderers.CustomJsonRenderer',
    )
}

有一种更简单的方法,只需更改serializer.py中的内容:

class CitySerializer(serializers.ModelSerializer):

    distance = serializers.SerializerMethodField()

    def get_distance(self, obj):

        return obj.distance.m

    class Meta:
        model = City
        fields = ('distance')

我建议不要使用.values(),而是使用serialiser。这样,当serialiser获取queryset时,您可以选择距离值并将其设置为值。我们找到了另一种方法。刚刚制作了一个渲染器,并将其用作django rest框架中的默认渲染器类。
在#models.py中,只需将distance=distance('position',p)更改为distance=distance('position',p).m即可。这样,您可以保持所有其他代码的原始状态,而不需要渲染器类。@ErionV这里的值
p
可能是动态的。这是一个更好的解决方案,第一个解决方案是一种过度使用