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.
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.)
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.
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',
]
I have verified the output on http://geojson.io to determine if its valid or not.
{
"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"
}
}
]
}
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 have now solved this issue with the following code:
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',
]
And this does indeed produce valid 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"
}
}
]
}
If someone has any inputs on this feel free to contribute and add an answer :-)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With