mhall119 has proposed merging lp:~mhall119/loco-directory/json-services into
lp:loco-directory.
Requested reviews:
loco-directory-dev (loco-directory-dev)
Related bugs:
#585307 export data to json
https://bugs.launchpad.net/bugs/585307
Provides read-only REST/JSON services for Django models used by LoCo Directory.
--
https://code.launchpad.net/~mhall119/loco-directory/json-services/+merge/26661
Your team loco-directory-dev is requested to review the proposed merge of
lp:~mhall119/loco-directory/json-services into lp:loco-directory.
=== modified file 'loco_directory/common/utils.py'
--- loco_directory/common/utils.py 2010-02-23 10:16:41 +0000
+++ loco_directory/common/utils.py 2010-06-03 03:50:38 +0000
@@ -1,5 +1,6 @@
import email
import os
+import django
def redirect(to, *args, **kwargs):
from distutils.version import LooseVersion as V
@@ -33,3 +34,81 @@
pass
return "version %s (rev %s)" % (version, bzr_revno)
+
+def model_has_field(model, field_name):
+ if isinstance(model, django.db.models.base.ModelBase):
+ model = model()
+ fields = field_name.split('__')
+ while len(fields) > 0:
+ name = fields[0]
+ fields = fields[1:]
+ try:
+ mf = model._meta.get_field(name)
+ if mf is not None and isinstance(mf, django.db.models.ForeignKey):
+ model = mf.rel.to()
+ except:
+ return False
+ return True
+
+def get_model_field(model, field_name):
+ if isinstance(model, django.db.models.base.ModelBase):
+ model = model()
+ fields = field_name.split('__')
+ while len(fields) > 0:
+ name = fields[0]
+ fields = fields[1:]
+ try:
+ mf = model._meta.get_field(name)
+ if mf is not None and isinstance(mf, django.db.models.ForeignKey):
+ model = mf.rel.to()
+ except:
+ pass
+ return mf
+
+def get_model_value(model, field_name):
+ value = None
+ fields = field_name.split('__')
+ while len(fields) > 0:
+ name = fields[0]
+ fields = fields[1:]
+ if hasattr(model, name):
+ value = getattr(model, name)
+ if isinstance(value, django.db.models.Model):
+ model = value
+ return value
+
+def corefilter_to_data(model):
+ filters = model.core_filters
+ data = {}
+
+ for (filter, value) in filters.items():
+ fields = filter.split('__')
+ field_name = fields[0]
+ while len(fields) > 0:
+ name = fields[0]
+ fields = fields[1:]
+
+ try:
+ if model.__class__.__name__ == 'ManyRelatedManager' or model.__class__.__name__ == 'RelatedManager':
+ mf = model.model._meta.get_field(name)
+ else:
+ mf = model._meta.get_field(name)
+
+ if mf is not None and isinstance(mf, django.db.models.ForeignKey):
+ model = mf.rel.to()
+ except:
+ pass
+
+ if name == 'pk':
+ name = 'id'
+ if model.__class__.__name__ == 'ManyRelatedManager' or model.__class__.__name__ == 'RelatedManager':
+ for f in model.model._meta.fields:
+ if f.column == name:
+ data[field_name] = value
+ elif isinstance(model, django.db.models.Model):
+ for f in model._meta.fields:
+ if f.column == name:
+ data[field_name] = value
+ else:
+ data[field_name] = value
+ return data
=== added directory 'loco_directory/services'
=== added file 'loco_directory/services/__init__.py'
--- loco_directory/services/__init__.py 1970-01-01 00:00:00 +0000
+++ loco_directory/services/__init__.py 2010-06-03 03:50:38 +0000
@@ -0,0 +1,135 @@
+'''
+Created on Jun 2, 2010
+
+...@author: mhall
+'''
+from django.db.models import Model
+from django.http import HttpResponse
+from django.forms.fields import EMPTY_VALUES
+from django.utils import simplejson
+from common import utils
+import re
+import decimal
+
+def model_service(model, request, url, include=None, exclude=None):
+ (instance_id, rem_url) = get_model_id(request, url)
+
+ try:
+ if instance_id is not None and instance_id != '':
+ return model_entity(model, request, url, include, exclude)
+ else:
+ return model_collection(model, request, url, include, exclude)
+ except Exception, e:
+ return HttpResponse(encode_error(e))
+
+def model_entity(model, request, url, include=None, exclude=None):
+ (entity_id, rem_url) = get_model_id(request, url)
+
+ try:
+ entity = model.objects.get(pk=entity_id)
+ except:
+ return HttpResponse(encode_error("Entity not found"))
+
+
+ # Otherwise process the entity request
+ if request.method == "GET":
+ return HttpResponse(encode(entity, include, exclude), mimetype=get_mimetype())
+
+ elif request.method == "PUT":
+ return HttpResponse(encode_error("Write operations are not supported"))
+
+ elif request.method == "DELETE":
+ return HttpResponse(encode_error("Write operations are not supported"))
+
+ return HttpResponse(encode_error("%s Not Implemented"%request.method))
+
+def model_collection(model, request, url, include=None, exclude=None):
+ if request.method == "GET":
+ results = do_search(model, request.GET, include, exclude)
+
+ collection = list(results)
+ return HttpResponse(encode(collection, include, exclude), mimetype=get_mimetype())
+
+ elif request.method == "POST":
+ return HttpResponse(encode_error("Write operations are not supported"))
+
+ return HttpResponse(encode_error("%s Not Implemented"%request.method))
+
+def do_search(model, request, include=None, exclude=None):
+ search_fields = include
+ if search_fields is None:
+ search_fields = [f.name for f in model._meta.local_fields+model._meta.many_to_many if not f.name.endswith("_ptr")]
+ if exclude is not None:
+ search_fields = [f for f in search_fields if f not in exclude]
+ search_values = dict([(str(key), value) for (key, value) in request.items()])
+
+ results = model.objects.filter(**search_values)
+
+ if '_sortby' in request and request['_sortby'] not in EMPTY_VALUES:
+ results = results.order_by(request.get('_sortby'))
+ return results
+
+def get_model_id(request, url):
+ instance_id = None
+ rem_url = None
+ if url is not None and len(url) > 0:
+ m = re.match(r"^([^/]+)/?(.*)", url)
+
+ if m is not None:
+ instance_id = m.group(1)
+ rem_url = m.group(2)
+ return (instance_id, rem_url)
+
+def encode(entity, include=None, exclude=None):
+ json = JSONEncoder(include, exclude)
+ return json.encode(entity)
+
+def decode(klass, entity, request, url=None):
+ return request.raw_post_data
+
+def get_mimetype():
+ return "application/json"
+
+def encode_error(error):
+ json = JSONEncoder()
+ return json.encode({'error': unicode(error)})
+
+class JSONEncoder(simplejson.JSONEncoder):
+
+ def __init__(self, include=None, exclude=None):
+ self.include = include
+ self.exclude = exclude
+ super(JSONEncoder, self).__init__()
+
+ def get_field_value(self, object, field):
+ f = getattr(object, field)
+ try:
+ if isinstance(f, Model):
+ if hasattr(f, 'pk'):
+ return self.default(f.pk)
+ else:
+ return None
+ if isinstance(f, decimal.Decimal):
+ return object._meta.get_field_by_name(field)[0]._format(f)
+ else:
+ return self.default(f)
+ except Exception:
+ return None
+
+ def default(self, o=None):
+
+ if isinstance(o, Model):
+ model_fields = self.include
+ if model_fields is None:
+ model_fields = [f.name for f in o._meta.fields+o._meta.many_to_many if not f.name.endswith("_ptr")]
+ if self.exclude is not None:
+ model_fields = [f for f in model_fields if f not in self.exclude]
+ d = dict([(field, self.get_field_value(o, field)) for field in model_fields])
+ return d
+ elif o.__class__.__name__ == 'ManyRelatedManager' or o.__class__.__name__ == 'RelatedManager':
+ return [r.pk for r in o.all()]
+ elif isinstance(o, (int, long, float)):
+ return o
+ elif o is None:
+ return None
+ return str(o)
=== added file 'loco_directory/services/urls.py'
--- loco_directory/services/urls.py 1970-01-01 00:00:00 +0000
+++ loco_directory/services/urls.py 2010-06-03 03:50:38 +0000
@@ -0,0 +1,20 @@
+'''
+Created on Jun 2, 2010
+
+...@author: mhall
+'''
+from django.conf.urls.defaults import *
+
+urlpatterns = patterns('',
+ #venues
+ url(r'^teams/(.*)$', 'services.views.team_service', name='team_service'),
+ url(r'^events/(.*)$', 'services.views.team_event_service', name='team_event_service'),
+ url(r'^global/(.*)$', 'services.views.global_event_service', name='global_event_service'),
+ url(r'^comments/(.*)$', 'services.views.event_comment_service', name='event_comment_service'),
+ url(r'^attendees/(.*)$', 'services.views.event_attendee_service', name='event_attendee_service'),
+ url(r'^venues/(.*)$', 'services.views.venue_service', name='venue_service'),
+ url(r'^users/(.*)$', 'services.views.user_service', name='user_service'),
+ url(r'^groups/(.*)$', 'services.views.group_service', name='group_service'),
+ url(r'^admins/(.*)$', 'services.views.admin_service', name='admin_service'),
+)
+
=== added file 'loco_directory/services/views.py'
--- loco_directory/services/views.py 1970-01-01 00:00:00 +0000
+++ loco_directory/services/views.py 2010-06-03 03:50:38 +0000
@@ -0,0 +1,39 @@
+'''
+Created on Jun 2, 2010
+
+...@author: mhall
+'''
+from teams.models import Team
+from events.models import GlobalEvent, TeamEvent, TeamEventComment, Attendee, TeamAdministrator
+from venues.models import Venue
+from django.contrib.auth.models import User, Group
+
+from services import model_service
+
+def team_service(request, url):
+ return model_service(Team, request, url)
+
+def team_event_service(request, url):
+ return model_service(TeamEvent, request, url)
+
+def global_event_service(request, url):
+ return model_service(GlobalEvent, request, url)
+
+def event_attendee_service(request, url):
+ return model_service(Attendee, request, url)
+
+def event_comment_service(request, url):
+ return model_service(TeamEventComment, request, url)
+
+def venue_service(request, url):
+ return model_service(Venue, request, url)
+
+def user_service(request, url):
+ return model_service(User, request, url, include=['id', 'username', 'groups'])
+
+def group_service(request, url):
+ return model_service(Group, request, url, exclude=['permissions'])
+
+def admin_service(request, url):
+ return model_service(TeamAdministrator, request, url)
+
\ No newline at end of file
=== modified file 'loco_directory/urls.py'
--- loco_directory/urls.py 2009-12-22 23:09:58 +0000
+++ loco_directory/urls.py 2010-06-03 03:50:38 +0000
@@ -15,6 +15,7 @@
url(r'^venues/', include('venues.urls')),
url(r'^logout$', 'common.views.site_logout'),
url(r'^jsi18n', 'django.views.i18n.javascript_catalog', name='jsi18n'),
+ url(r'^services/', include('services.urls')),
)
if settings.STATIC_SERVE:
_______________________________________________
Mailing list: https://launchpad.net/~loco-directory-dev
Post to : [email protected]
Unsubscribe : https://launchpad.net/~loco-directory-dev
More help : https://help.launchpad.net/ListHelp