Skip to content

Instantly share code, notes, and snippets.

@ingenieroariel
Created August 28, 2009 18:37
Show Gist options
  • Save ingenieroariel/177140 to your computer and use it in GitHub Desktop.
Save ingenieroariel/177140 to your computer and use it in GitHub Desktop.
BME piston api for Remco
#!/usr/bin/env python
# encoding: utf-8
"""
emitters.py
Created by Ariel Nunez on 2009-05-24.
Copyright (c) 2009 Burning Man Earth. All rights reserved.
"""
from __future__ import generators
import types, decimal, types, re, inspect
from piston.emitters import JSONEmitter
from django.core.serializers.json import DjangoJSONEncoder
from django.contrib.gis.geos import fromstr
import simplejson
from django.db.models.query import QuerySet
from django.db.models import Model, permalink
from django.utils import simplejson
from django.utils.xmlutils import SimplerXMLGenerator
from django.utils.encoding import smart_unicode
from django.core.serializers.json import DateTimeAwareJSONEncoder
from django.http import HttpResponse
from django.core import serializers
from django.contrib.gis.geos.geometry import GEOSGeometry
class GeoJSONEmitter(JSONEmitter):
"""
GeoJSON emitter, understands timestamps and GIS objects
"""
def construct(self):
"""
Recursively serialize a lot of types, and
in cases where it doesn't recognize the type,
it will fall back to Django's `smart_unicode`.
Returns `dict`.
"""
def _any(thing, fields=()):
"""
Dispatch, all types are routed through here.
"""
ret = None
if isinstance(thing, QuerySet):
ret = _qs(thing, fields=fields)
elif isinstance(thing, (tuple, list)):
ret = _list(thing)
elif isinstance(thing, dict):
ret = _dict(thing)
elif isinstance(thing, decimal.Decimal):
ret = str(thing)
elif isinstance(thing, Model):
ret = _model(thing, fields=fields)
elif isinstance(thing, HttpResponse):
raise HttpStatusCode(thing.content, code=thing.status_code)
elif isinstance(thing, types.FunctionType):
if not inspect.getargspec(thing)[0]:
ret = _any(thing())
elif isinstance(thing, GEOSGeometry):
ret = thing.geojson
else:
ret = smart_unicode(thing, strings_only=True)
return ret
def _fk(data, field):
"""
Foreign keys.
"""
return _any(getattr(data, field.name))
def _related(data, fields=()):
"""
Foreign keys.
"""
return [ _model(m, fields) for m in data.iterator() ]
def _m2m(data, field, fields=()):
"""
Many to many (re-route to `_model`.)
"""
return [ _model(m, fields) for m in getattr(data, field.name).iterator() ]
def _model(data, fields=()):
"""
Models. Will respect the `fields` and/or
`exclude` on the handler (see `typemapper`.)
"""
ret = { }
handler = self.in_typemapper(type(data), self.anonymous)
get_absolute_uri = False
if handler or fields:
v = lambda f: getattr(data, f.attname)
if not fields:
"""
Fields was not specified, try to find teh correct
version in the typemapper we were sent.
"""
mapped = self.in_typemapper(type(data), self.anonymous)
get_fields = set(mapped.fields)
exclude_fields = set(mapped.exclude).difference(get_fields)
if 'absolute_uri' in get_fields:
get_absolute_uri = True
if not get_fields:
get_fields = set([ f.attname.replace("_id", "", 1)
for f in data._meta.fields ])
# sets can be negated.
for exclude in exclude_fields:
if isinstance(exclude, basestring):
get_fields.discard(exclude)
elif isinstance(exclude, re._pattern_type):
for field in get_fields.copy():
if exclude.match(field):
get_fields.discard(field)
else:
get_fields = set(fields)
met_fields = self.method_fields(handler, get_fields)
for f in data._meta.local_fields:
if f.serialize and f.attname not in met_fields:
if not f.rel:
if f.attname in get_fields:
ret[f.attname] = _any(v(f))
get_fields.remove(f.attname)
else:
if f.attname[:-3] in get_fields:
ret[f.name] = _fk(data, f)
get_fields.remove(f.name)
for mf in data._meta.many_to_many:
if mf.serialize and mf.attname not in met_fields:
if mf.attname in get_fields:
ret[mf.name] = _m2m(data, mf)
get_fields.remove(mf.name)
# try to get the remainder of fields
for maybe_field in get_fields:
if isinstance(maybe_field, (list, tuple)):
model, fields = maybe_field
inst = getattr(data, model, None)
if inst:
if hasattr(inst, 'all'):
ret[model] = _related(inst, fields)
elif callable(inst):
if len(inspect.getargspec(inst)[0]) == 1:
ret[model] = _any(inst(), fields)
else:
ret[model] = _model(inst, fields)
elif maybe_field in met_fields:
# Overriding normal field which has a "resource method"
# so you can alter the contents of certain fields without
# using different names.
ret[maybe_field] = _any(met_fields[maybe_field](data))
else:
maybe = getattr(data, maybe_field, None)
if maybe:
if isinstance(maybe, (int, basestring)):
ret[maybe_field] = _any(maybe)
elif callable(maybe):
if len(inspect.getargspec(maybe)[0]) == 1:
ret[maybe_field] = _any(maybe())
else:
handler_f = getattr(handler or self.handler, maybe_field, None)
if handler_f:
ret[maybe_field] = _any(handler_f(data))
else:
for f in data._meta.fields:
ret[f.attname] = _any(getattr(data, f.attname))
fields = dir(data.__class__) + ret.keys()
add_ons = [k for k in dir(data) if k not in fields]
for k in add_ons:
ret[k] = _any(getattr(data, k))
# resouce uri
if self.in_typemapper(type(data), self.anonymous):
handler = self.in_typemapper(type(data), self.anonymous)
if hasattr(handler, 'resource_uri'):
url_id, fields = handler.resource_uri()
ret['resource_uri'] = permalink( lambda: (url_id,
(getattr(data, f) for f in fields) ) )()
if hasattr(data, 'get_api_url') and 'resource_uri' not in ret:
try: ret['resource_uri'] = data.get_api_url()
except: pass
# absolute uri
if hasattr(data, 'get_absolute_url') and get_absolute_uri:
try: ret['absolute_uri'] = data.get_absolute_url()
except: pass
return ret
def _qs(data, fields=()):
"""
Querysets.
"""
return [ _any(v, fields) for v in data ]
def _list(data):
"""
Lists.
"""
return [ _any(v) for v in data ]
def _dict(data):
"""
Dictionaries.
"""
return dict([ (k, _any(v)) for k, v in data.iteritems() ])
# Kickstart the seralizin'.
return _any(self.data, self.fields)
import logging
from piston.handler import BaseHandler, AnonymousBaseHandler
from piston.emitters import Emitter, JSONEmitter
from brc.models import *
from api.emitters import GeoJSONEmitter
from swingtime.models import Event, Occurrence
import time
JSONEmitter.unregister('json')
Emitter.register('json', GeoJSONEmitter, content_type='text/javascript; charset=utf-8')
art_fields = ('id', 'name', ('year', ('id','year')), 'slug', 'artist', 'description', 'url', 'contact_email', 'location_point', 'location_poly', 'circular_street', 'time_address')
event_fields = ('id', 'title','description', 'print_description', ('year', ('id','year')), 'slug', 'event_type', ('hosted_by_camp', ('id','name')), ('located_at_art', ('id','name')), 'other_location', 'check_location', 'url', 'location_point', 'location_track', 'all_day', ('occurrence_set', ('start_time', 'end_time')))
camp_fields = ('id', ('year', ('id','year')), 'name', 'description', 'type', 'start_date_time', 'end_date_time', 'duration', 'repeats', 'hosted_by_camp', 'located_at_art', 'url', 'contact_email')
cstreet_fields = ('id', ('year', ('id','year')), 'name', 'order', 'width', 'distance_from_center', 'street_line')
tstreet_fields = ('id', ('year', ('id','year')), 'hour', 'minute', 'name', 'width', 'street_line')
infrastructure_fields = ('id', ('year', ('id','year')), 'name', 'location_point', 'location_line', 'location_poly', 'location_multigeom', 'tags')
year_fields = ('id', 'location', 'location_point', 'participants', 'theme')
user_fields = ('id', 'username', 'first_name', 'last_name', 'active')
class AnonymousArtInstallationHandler(BaseHandler):
allow_methods = ('GET',)
model = ArtInstallation
fields = art_fields
def read(self, request, year_year=None, art_id=None):
base = ArtInstallation.objects.filter()
if(year_year):
year = Year.objects.get(year=year_year)
if(art_id):
art = ArtInstallation.objects.filter(year=year,id=art_id)
else:
art = ArtInstallation.objects.filter(year=year)
return art
else:
return base.all()
class ArtInstallationHandler(BaseHandler):
allow_methods = ('GET',)
model = ArtInstallation
fields = art_fields
anonymous = AnonymousArtInstallationHandler
class AnonymousPlayaEventHandler(AnonymousBaseHandler):
allow_methods = ('GET',)
model = PlayaEvent
fields = event_fields
def read(self, request, year_year=None, playa_event_id=None):
base = PlayaEvent.objects.filter(moderation='A', list_online=True)
if(year_year):
year = Year.objects.get(year=year_year)
if(playa_event_id):
events = PlayaEvent.objects.filter(year=year,id=playa_event_id)
else:
if(request.GET.get('start_time') and request.GET.get('end_time')):
event_list = Occurrence.objects.filter(start_time__gte=request.GET.get('start_time'), end_time__lte=request.GET.get('end_time')).values_list('event', flat=True)
events = PlayaEvent.objects.filter(id__in=event_list)
elif(request.GET.get('start_time')):
event_list = Occurrence.objects.filter(start_time__gte=request.GET.get('start_time')).values_list('event', flat=True)
events = PlayaEvent.objects.filter(id__in=event_list)
elif(request.GET.get('end_time')):
event_list = Occurrence.objects.filter(end_time__lte=request.GET.get('end_time')).values_list('event', flat=True)
events = PlayaEvent.objects.filter(id__in=event_list)
else:
events = PlayaEvent.objects.filter(year=year)
return events
else:
return base.all()
class PlayaEventHandler(BaseHandler):
allow_methods = ('GET',)
model = PlayaEvent
anonymous = AnonymousPlayaEventHandler
fields = event_fields
class AnonymousThemeCampHandler(AnonymousBaseHandler):
allow_methods = ('GET',)
model = ThemeCamp
fields = camp_fields
def read(self, request, year_year=None, camp_id=None):
base = ThemeCamp.objects.filter()
if(year_year):
year = Year.objects.get(year=year_year)
if(camp_id):
camp = ThemeCamp.objects.filter(year=year,id=camp_id)
else:
camp = ThemeCamp.objects.filter(year=year)
return camp
else:
return base.all()
class ThemeCampHandler(BaseHandler):
allow_methods = ('GET',)
model = ThemeCamp
fields = camp_fields
anonymous = AnonymousThemeCampHandler
class AnonymousCircularStreetHandler(AnonymousBaseHandler):
allow_methods = ('GET',)
model = CircularStreet
fields = cstreet_fields
def read(self, request, year_year=None):
base = CircularStreet.objects.filter()
if(year_year):
year = Year.objects.get(year=year_year)
cstreet = CircularStreet.objects.filter(year=year)
return cstreet
else:
return base.all()
class CircularStreetHandler(BaseHandler):
allow_methods = ('GET',)
model = CircularStreet
fields = cstreet_fields
anonymous = AnonymousCircularStreetHandler
class AnonymousTimeStreetHandler(AnonymousBaseHandler):
allow_methods = ('GET',)
model = TimeStreet
fields = tstreet_fields
def read(self, request, year_year=None):
base = TimeStreet.objects.filter()
if(year_year):
year = Year.objects.get(year=year_year)
tstreet = TimeStreet.objects.filter(year=year)
return tstreet
else:
return base.all()
class TimeStreetHandler(BaseHandler):
allow_methods = ('GET',)
model = TimeStreet
fields = tstreet_fields
anonymous = AnonymousTimeStreetHandler
class AnonymousInfrastructureHandler(AnonymousBaseHandler):
allow_methods = ('GET',)
model = Infrastructure
fields = infrastructure_fields
def read(self, request, year_year=None):
base = Infrastructure.objects.filter()
if(year_year):
year = Year.objects.get(year=year_year)
infrastructure = Infrastructure.objects.filter(year=year)
return infrastructure
else:
return base.all()
class InfrastructureHandler(BaseHandler):
allow_methods = ('GET',)
model = Infrastructure
fields = infrastructure_fields
anonymous = AnonymousInfrastructureHandler
class AnonymousYearHandler(AnonymousBaseHandler):
allow_methods = ('GET',)
model = Year
fields = year_fields
class YearHandler(BaseHandler):
allow_methods = ('GET',)
model = Year
fields = year_fields
anonymous = AnonymousYearHandler
class UserHandler(BaseHandler):
allow_methods = ('GET',)
model = User
fields = user_fields
from django.conf.urls.defaults import *
from piston.resource import Resource
from api.handlers import *
from piston.authentication import OAuthAuthentication
auth = OAuthAuthentication()
year_handler = Resource(YearHandler, authentication=auth)
camp_handler = Resource(ThemeCampHandler, authentication=auth)
art_handler = Resource(ArtInstallationHandler, authentication=auth)
event_handler = Resource(PlayaEventHandler, authentication=auth)
user_handler = Resource(UserHandler, authentication=auth)
cstreet_handler = Resource(CircularStreetHandler, authentication=auth)
tstreet_handler = Resource(TimeStreetHandler, authentication=auth)
infrastructure_handler = Resource(InfrastructureHandler, authentication=auth)
urlpatterns = patterns('',
url(r'^user/', user_handler),
url(r'^year/', year_handler),
url(r'^(?P<year_year>\d{4})/camp/(?P<camp_id>\d+)/$', camp_handler),
url(r'^(?P<year_year>\d{4})/camp/', camp_handler),
url(r'^(?P<year_year>\d{4})/art/(?P<art_id>\d+)/$', art_handler),
url(r'^(?P<year_year>\d{4})/art/', art_handler),
url(r'^(?P<year_year>\d{4})/event/(?P<playa_event_id>\d+)/$', event_handler),
url(r'^(?P<year_year>\d{4})/event/', event_handler),
url(r'^(?P<year_year>\d{4})/cstreet/', cstreet_handler),
url(r'^(?P<year_year>\d{4})/tstreet/', tstreet_handler),
url(r'^(?P<year_year>\d{4})/infrastructure/', infrastructure_handler),
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment