I have searched long and far for a solution that is up to date and specific to my problem but have yet not found a solution or a clear documentation on what I really need to do in order to flatten a relationship to become geojson compliant.
This question is almost identical to mine, however the solutions or answers does not solve the problem and still produces invalid GeoJSON.
Related
- Set serializer geo_field as PointField from another model - Django
- Django REST Framework: define fields in nested object?
Problem
I have a Location
model that holds a pointfield
with SRID=4326. I also have a TrainStation
model that has location
field as foreign key to Location
. When I serialize the TrainStation
via the GeoFeatureModelSerializer
it produces invalid GeoJSON (see example below "invalid geojson").
(Valid GeoJSON can, of course, be obtained if I where to store the PointField
in the TrainStation
model, but in my case, I cannot do that so I need to flatten it somehow.)
Question
- How do I achieve output like the "Valid GeoJSON" example below?
Research
I am a newcomer to both Python and Django thus I am yet not very good at reading other people's source code, however I think I can conclude that I need to somehow override the to_representation()
method in order to get what I want, but my searches are so far fruitless so I am stuck.
models.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)
serializers.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 Output examples:
I have verified the output on http://geojson.io to determine if its valid or not.
Invalid 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"
}
}
]
}
Valid GeoJSON
This is the output I am looking for.
{
"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"
}
}
]
}
I think the problem might be that you're declaring a whole ModelSerializer as your geo_field and its just sticking the result of that serializer, which is itself an entire geojson object, inside the geometry part of your main geojson object and the Serializers that come with django-restframework-gis just don't know what to do about that.
What the
GeoFeatureModelSerializer
class would like to see as a geo_field is aGeometryField
which has been serialized by its ownrest_framework_gis.fields.GeometryField
. I imagine any of the following would get you the behavior you want.just add location.point to your TrainStationSerializer as its geofield using the double underscore format. Disclaimer: I'm not actually sure off the top of my head if drf-gis implements the double underscores properly for the geo_field property, but I think this should work.
Use the
fields.GeometryField
class that comes with drf-gis and specify your location.point field as its source.Use the
GeometrySerializerMethodField
as shown in the example on drf-gis's readme