6

我已经搜索了很长时间,以寻找一个最新的和特定于我的问题的解决方案,但还没有找到解决方案或明确的文档,说明我真正需要做什么才能使关系扁平化以符合 geojson 标准。

这个问题与我的几乎相同,但是解决方案或答案并不能解决问题,并且仍然会产生无效的 GeoJSON。

有关的

问题

我有一个包含 SRID=4326的Location模型。pointfield我还有一个TrainStation模型,它location外键Location. 当我TrainStation通过GeoFeatureModelSerializer它序列化它时,它会产生无效的 GeoJSON(参见下面的示例“无效的 geojson”)。

(当然,如果我将其存储PointFieldTrainStation模型中的哪个位置,则可以获得有效的 GeoJSON,但在我的情况下,我不能这样做,所以我需要以某种方式将其展平。)

问题

  • 如何实现像下面的“Valid GeoJSON”示例这样的输出?

研究

我是 Python 和 Django 的新手,因此我还不太擅长阅读其他人的源代码,但是我认为我可以得出结论,我需要以某种方式覆盖该to_representation()方法以获得我想要的东西,但我的搜索是如此远没有结果,所以我被困住了。

模型.py

class Location(models.Model):

    point = models.PointField()

class TrainStation(models.Model):

    location_signature = models.CharField(primary_key=True, max_length=32)
    advertised_location_name = models.CharField(max_length=32)
    country_code = models.ForeignKey(Country)
    county_no = models.ForeignKey(County)
    location = models.ForeignKey(Location, null=True)

序列化程序.py

class LocationSerializer(ModelSerializer):

    class Meta:
        model = Location
        geo_field = 'point'
        fields = [
            'point',
        ]


class TrainStationSerializer(GeoFeatureModelSerializer):

    location_signature = PrimaryKeyRelatedField(read_only=True)
    location = LocationSerializer(read_only=True)
    country_code = StringRelatedField(read_only=True)
    county_no = StringRelatedField(read_only=True)

    class Meta:
        model = TrainStation
        geo_field = 'location'
        fields = [
            'location_signature',
            'advertised_location_name',
            'country_code',
            'county_no',
        ]

GeoJSON 输出示例:

我已经验证了http://geojson.io上的输出以确定它是否有效。

无效的 GeoJSON

{
    "type": "FeatureCollection",
    "features": [
        {
            "id": "Ak",
            "type": "Feature",
            "geometry": {
                "point": {           <------+------ offending lines
                    "type": "Point",        |
                    "coordinates": [        |
                        18.8303462142963,   |
                        68.3486410812835    |
                    ]                       |
                }                    <------+
            },
            "properties": {
                "advertised_location_name": "Abisko Östra",
                "country_code": "Sverige",
                "county_no": "Norrbottens län"
            }
        }
    ]
}

有效的 GeoJSON

这是我正在寻找的输出。

{
    "type": "FeatureCollection",
    "features": [
        {
            "id": "Ak",
            "type": "Feature",
            "geometry": {
                "type": "Point",
                "coordinates": [
                    18.8303462142963,
                    68.3486410812835
                ]
            },
            "properties": {
                "advertised_location_name": "Abisko Östra",
                "country_code": "Sverige",
                "county_no": "Norrbottens län"
            }
        }
    ]
}
4

2 回答 2

3

我现在用以下代码解决了这个问题:

class LocationSerializer(ModelSerializer):

    def to_representation(self, obj):

        representation = super().to_representation(obj)
        point_representation = representation.pop('point')
        for key in point_representation:
            representation[key] = point_representation[key]

        return representation

    class Meta:
        model = Location
        geo_field = 'point'
        fields = [
            'point',
        ]

这确实会产生有效的 GeoJSON:

{
    "type": "FeatureCollection",
    "features": [
        {
            "id": "Ak",
            "type": "Feature",
            "geometry": {
                "type": "Point",
                "coordinates": [
                    18.8303462142963,
                    68.3486410812835
                ]
            },
            "properties": {
                "advertised_location_name": "Abisko Östra",
                "country_code": "Sverige",
                "county_no": "Norrbottens län"
            }
        }
    ]
}

如果有人对此有任何意见,请随时贡献并添加答案:-)

于 2017-07-02T01:24:48.070 回答
0

我认为问题可能在于您将整个 ModelSerializer 声明为您的 geo_field 并且它只是将该序列化程序的结果(它本身就是一个完整的 geojson 对象)粘贴在您的主要 geojson 对象的几何部分和附带的序列化程序中django-restframework-gis 只是不知道该怎么做。

该类GeoFeatureModelSerializer希望看到的 geo_field 是一个GeometryField已由其自己序列化的rest_framework_gis.fields.GeometryField. 我想以下任何一项都会让你得到你想要的行为。

  1. 只需使用双下划线格式将 location.point 添加到您的 TrainStationSerializer 作为其地理字段。 免责声明:如果 drf-gis 为 geo_field 属性正确实现双下划线,我实际上并不确定,但我认为这应该有效。

    from rest_framework_gis.fields import GeometryField
    from rest_framework_gis.serializers import GeoFeatureModelSerializer
    
    
    class TrainStationSerializer(GeoFeatureModelSerializer):
    
        location_signature = PrimaryKeyRelatedField(read_only=True)
        country_code = StringRelatedField(read_only=True)
        county_no = StringRelatedField(read_only=True)
    
        class Meta:
            model = TrainStation
            geo_field = 'location__point'
            fields = [
                'location_signature',
                'advertised_location_name',
                'country_code',
                'county_no',
            ]
    
  2. 使用fields.GeometryFielddrf-gis 附带的类并指定您的 location.point 字段作为其源。

    from rest_framework_gis.fields import GeometryField
    from rest_framework_gis.serializers import GeoFeatureModelSerializer
    
    
    class TrainStationSerializer(GeoFeatureModelSerializer):
    
        location_signature = PrimaryKeyRelatedField(read_only=True)
        location = GeometryField(source='location.point')
        country_code = StringRelatedField(read_only=True)
        county_no = StringRelatedField(read_only=True)
    
        class Meta:
            model = TrainStation
            geo_field = 'location'
            fields = [
                'location_signature',
                'advertised_location_name',
                'country_code',
                'county_no',
            ]
    
  3. 使用GeometrySerializerMethodFielddrf-gis 自述文件中的示例所示

    from rest_framework_gis.fields import GeometrySerializerMethodField
    from rest_framework_gis.serializers import GeoFeatureModelSerializer
    
    
    class TrainStationSerializer(GeoFeatureModelSerializer):
    
        location_signature = PrimaryKeyRelatedField(read_only=True)
        location = GeometrySerializerMethodField()
        country_code = StringRelatedField(read_only=True)
        county_no = StringRelatedField(read_only=True)
    
        def get_location(self, obj):
            return obj.location.point
    
        class Meta:
            model = TrainStation
            geo_field = 'location'
            fields = [
                'location_signature',
                'advertised_location_name',
                'country_code',
                'county_no',
            ]
    
于 2017-07-15T19:27:34.100 回答