我已经远远地搜索了一个最新且特定于我的问题的解决方案,但是还没有找到解决方案或明确的文档来说明我真正需要做什么才能使关系变得扁平化以符合geojson标准
这个问题几乎与我的问题相同,但是解决方案或答案 没有解决问题,仍然产生无效的GeoJSON。
我有一个Location
模型,其中包含pointfield
,SRID = 4326。我还有一个TrainStation
模型,其location
字段为外键到Location
。当我通过TrainStation
序列化GeoFeatureModelSerializer
时,它会生成无效的GeoJSON(请参阅下面的示例"无效的geojson")。
(当然,如果我将PointField
存储在TrainStation
模型中,可以获得有效的GeoJSON,但在我的情况下,我不能这样做,所以我需要展平不知何故。)
我是Python和Django的新手,因此我不太擅长阅读其他人的源代码,但我想我可以得出结论,我需要以某种方式覆盖to_representation()
方法为了得到我想要的东西,但我的搜索到目前为止还没有结果,所以我被困住了。
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)
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',
]
我已验证http://geojson.io上的输出以确定其是否有效。
{
"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"
}
}
]
}
这是我要找的输出。
{
"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"
}
}
]
}
答案 0 :(得分:1)
我现在用以下代码解决了这个问题:
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"
}
}
]
}
如果有人对此有任何意见,请随时提供答案并添加答案: - )
答案 1 :(得分:0)
我认为问题可能是您将整个ModelSerializer声明为geo_field并且它只是在主geojson对象的几何部分和Serializers中粘贴了该序列化器的结果,该序列化器本身就是一个完整的geojson对象。与django-restframework-gis一起来的只是不知道该怎么做。
GeoFeatureModelSerializer
类希望看作geo_field的是GeometryField
,它已由自己的rest_framework_gis.fields.GeometryField
序列化。我想以下任何一种都能让你得到你想要的行为。
使用双下划线格式将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',
]
使用drf-gis附带的fields.GeometryField
类,并指定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',
]
GeometrySerializerMethodField
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',
]