在Django GeoJSON序列化器字段中指定相关模型的字段

时间:2019-05-13 05:33:58

标签: python django geojson django-serializer

我正在尝试使用 geojson序列化器在地图上绘制latlong点。对于此功能,我有两个名为ActivityClusterA的模型。

活动是用于存储项目中定义的某些活动的数据的模型。该活动包含一个名为PointField的{​​{1}}字段。 这是我的location模型:

Activity

类似地,一个活动可以属于一个集群。此数据存储在模型 ClusterA (集群活动)中。 集群A 是指特定于集群的活动。

集群模型

class Activity(models.Model):
    name = models.CharField(max_length=200)
    description = models.CharField(max_length=500)
    target_number = models.IntegerField(null=True, blank=True)
    target_unit = models.CharField(max_length=200, null=True, blank=True)
    beneficiary_level = models.BooleanField(default=True)
    weight = models.FloatField(default=0)
    location = PointField(geography=True, srid=4326, blank=True, null=True)

    def __str__(self):
        return self.name

    @property
    def latitude(self):
        if self.location:
            return self.location.y

    @property
    def longitude(self):
        if self.location:
            return self.location.x

ClusterA模型

class Cluster(models.Model):
    name = models.CharField(max_length=200)
    ward = models.CharField(max_length=200)

    def __str__(self):
        return self.name

现在我正在使用一个函数,该函数返回集群活动的geojson数据为:

class ClusterA(models.Model):
    activity = models.ForeignKey('Activity', related_name='clustera')
    target_number = models.IntegerField(null=True, blank=True, default=0)
    target_unit = models.CharField(max_length=200, null=True, blank=True, default='')
    time_interval = models.ForeignKey(ProjectTimeInterval, related_name='cainterval', null=True, blank=True)
    target_completed = models.IntegerField(null=True, blank=True, default=0)
    interval_updated = models.BooleanField(default=False)
    target_updated = models.BooleanField(default=False)
    location = PointField(geography=True, srid=4326, blank=True, null=True)

    def __str__(self):
        return self.name

    @property
    def latitude(self):
        if self.location:
            return self.location.y

    @property
    def longitude(self):
        if self.location:
            return self.location.x

    def save(self, force_insert=False, force_update=False, using=None, update_fields=None):
        if not self.id:
            if not self.activity.beneficiary_level:
                self.target_unit = self.activity.target_unit
            self.time_interval = self.activity.time_interval
        return super(ClusterA, self).save()

我得到的输出是:

def get_map_data(request):
    ca = ClusterA.objects.all()
    data = serialize(
        'geojson',
        ca,
        geometry_field='location',
        fields = ('activity', 'location', )
    )
    print(data)
    return HttpResponse(data)

活动字段提供了活动的ID。但是我需要活动名称,以便我可以在地图上绘制的标记的弹出窗口中显示活动名称。

这是我试图在标记的弹出窗口中显示活动名称的方法:

{"type": "FeatureCollection", "crs": {"type": "name", "properties": {"name": "EPSG:4326"}}, "features": [{"geometry": {"type": "Point", "coordinates": [85.336775, 27.542718]}, "type": "Feature", "properties": {"activity": 27}}, {"geometry": null, "type": "Feature", "properties": {"activity": 19}}, {"geometry": {"type": "Point", "coordinates": [85.336776, 27.735227]}, "type": "Feature", "properties": {"activity": 26}}]}

如果我将本地模型的字段传递给它,则弹出窗口将显示其他数据。

我尝试使用:

onEachFeature: function (feature, layer) {
   layer.bindPopup(feature.properties.name);
} 

get_map_data 函数中,但它不会在打印输出中将字段显示为:

fields = ('activity__name', 'location', )

如您所见,以上输出的{"type": "FeatureCollection", "crs": {"type": "name", "properties": {"name": "EPSG:4326"}}, "features": [{"geometry": {"type": "Point", "coordinates": [85.336775, 27.542718]}, "type": "Feature", "properties": {}}, {"geometry": null, "type": "Feature", "properties": {}}, {"geometry": {"type": "Point", "coordinates": [85.336776, 27.735227]}, "type": "Feature", "properties": {}}]} 中没有指定任何字段。

我需要的帮助是能够获取活动模型的名称字段而不是ID。

我正在使用properties

2 个答案:

答案 0 :(得分:1)

默认情况下,Django序列化器不提供ForeignKey值。因此,您可以覆盖geojson序列化器字段。例如:

from django.contrib.gis.serializers.geojson import Serializer 

class CustomSerializer(Serializer):

    def end_object(self, obj):
        for field in self.selected_fields:
            if field == 'pk':
                continue
            elif field in self._current.keys():
                continue
            else:
                try:
                    if '__' in field:
                        fields = field.split('__')
                        value = obj
                        for f in fields:
                            value = getattr(value, f)
                        if value != obj:
                            self._current[field] = value

                except AttributeError:
                    pass
        super(CustomSerializer, self).end_object(obj)

用法:

serializers = CustomSerializer()
ca = ClusterA.objects.all()
data = serializers.serialize(ca, geometry_field='location', fields=('activity__name', 'location', ))

答案 1 :(得分:0)

我相信您需要做的就是使用JOIN属性来.select_related()活动表:

def get_map_data(request):
    ca = ClusterA.objects.all().select_related()
    data = serialize(
        'geojson',
        ca,
        geometry_field='location',
        fields = ('activity', 'location', )
    )

让我知道尝试此操作时会发生什么。

如果这不起作用,请尝试:

def get_map_data(request):
    ca = ClusterA.objects.all().select_related('activity__name')
    data = serialize(
        'geojson',
        ca,
        geometry_field='location',
        fields = ('activity', 'location', )
    )