-
-
Save cspanring/1771937 to your computer and use it in GitHub Desktop.
# Shamelessly stolen from https://github.com/newsapps/django-boundaryservice/blob/master/boundaryservice/tastyhacks.py | |
from django.contrib.gis.db.models import GeometryField | |
from django.utils import simplejson | |
from tastypie.bundle import Bundle | |
from tastypie.fields import ApiField, CharField | |
from tastypie.resources import ModelResource | |
class GeometryApiField(ApiField): | |
""" | |
Custom ApiField for dealing with data from GeometryFields (by serializing them as GeoJSON). | |
""" | |
dehydrated_type = 'geometry' | |
help_text = 'Geometry data.' | |
def hydrate(self, bundle): | |
value = super(GeometryApiField, self).hydrate(bundle) | |
if value is None: | |
return value | |
return simplejson.dumps(value) | |
def dehydrate(self, obj): | |
return self.convert(super(GeometryApiField, self).dehydrate(obj)) | |
def convert(self, value): | |
if value is None: | |
return None | |
if isinstance(value, dict): | |
return value | |
# Get ready-made geojson serialization and then convert it _back_ to a Python object | |
# so that Tastypie can serialize it as part of the bundle | |
return simplejson.loads(value.geojson) | |
class GeoResource(ModelResource): | |
""" | |
ModelResource subclass that handles geometry fields as GeoJSON. | |
""" | |
@classmethod | |
def api_field_from_django_field(cls, f, default=CharField): | |
""" | |
Overrides default field handling to support custom GeometryApiField. | |
""" | |
if isinstance(f, GeometryField): | |
return GeometryApiField | |
return super(GeoResource, cls).api_field_from_django_field(f, default) |
Also, how do I POST/PUT/PATCH to the GeometryApiField? I tried the same data that was returned by GET, but I am getting ``cannot set Order GeometryProxy with value of type: dict` exception
so, whoever needs to POST/PUT/PATCH on GeometryApiField, add the following method into the GeometryApiField:
def hydrate(self, bundle):
value = super(GeometryApiField, self).hydrate(bundle)
return simplejson.dumps(value)
excellent, thanks! will try it in an upcoming project.
here's a little bugfix for a case when value is None:
def hydrate(self, bundle):
value = super(GeometryApiField, self).hydrate(bundle)
if value is None:
return value
return simplejson.dumps(value)
This seems to work great! I've started a tastypie branch to work on geo-related stuff. The idea is you'd be able to do something like:
from tastypie.contrib.gis.resources import ModelResource
class MyResource(ModelResource):
...
which would be more in line with how Django handles gis stuff in general. I think this should be included in tastypie, but if not we can break off into a separate tastypie-contrib repository.
this seems like a good approach. did you discuss this with tastypie maintainers or post a pull request?
I will issue a pull request once I'm satisfied that my branch is working right. And once I have tests + docs :)
I am trying to use this code, it works fine, however do you have an idea why the coordinates are getting stripped down to 10 characters?