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

Reply via email to