← Back to team overview

harvest-dev team mailing list archive

[Merge] lp:~dholbach/harvest/581730 into lp:harvest

 

Daniel Holbach has proposed merging lp:~dholbach/harvest/581730 into lp:harvest.

Requested reviews:
  harvest-dev (harvest-dev)
Related bugs:
  #581730 dump data to json
  https://bugs.launchpad.net/bugs/581730

-- 
https://code.launchpad.net/~dholbach/harvest/581730/+merge/33387
Your team harvest-dev is requested to review the proposed merge of lp:~dholbach/harvest/581730 into lp:harvest.
=== added directory 'harvest/services'
=== added file 'harvest/services/__init__.py'
--- harvest/services/__init__.py	1970-01-01 00:00:00 +0000
+++ harvest/services/__init__.py	2010-08-23 14:17:40 +0000
@@ -0,0 +1,155 @@
+# Portions of this code comes from the Oct09 project
+# developed by the Moffitt Cancer Center.
+# License: http://bitbucket.org/oct09/main/src/tip/COPYING
+# Project: http://bitbucket.org/oct09/main/wiki/Home
+
+from django.db.models import Model
+from django.http import HttpResponse
+from django.forms.fields import EMPTY_VALUES
+from django.utils import simplejson
+import re
+import decimal
+
+CHUNK_SIZE = 500
+
+def parse_number_argument(arguments, which):
+    if not arguments.has_key(which):
+        return None
+    if arguments[which] in EMPTY_VALUES:
+        return None
+    try:
+        number = int(arguments[which])
+    except:
+        number = None
+    return number
+
+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()])
+
+    extra_arguments = {}
+    for key in search_values.keys():
+        if key.startswith('_'):
+            extra_arguments[key] = search_values.pop(key)
+    offset = parse_number_argument(extra_arguments, '_offset')
+    length = parse_number_argument(extra_arguments, '_length')
+    if not length or length > CHUNK_SIZE:
+        length = CHUNK_SIZE
+    results = model.objects.filter(**search_values)[offset:length]
+
+    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, o, field):
+        f = getattr(o, field)
+        try:
+            if isinstance(f, Model):
+                if hasattr(f, 'pk'):
+                    return self.default(f.pk)
+                else:
+                    return None
+            if isinstance(f, decimal.Decimal):
+                return o._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 'harvest/services/urls.py'
--- harvest/services/urls.py	1970-01-01 00:00:00 +0000
+++ harvest/services/urls.py	2010-08-23 14:17:40 +0000
@@ -0,0 +1,12 @@
+from django.conf.urls.defaults import *
+
+urlpatterns = patterns('',
+    url(r'^users/(.*)$', 'services.views.user_service', name='user_service'),
+    url(r'^packagesets/(.*)$', 'services.views.packageset_service', name='packageset_service'),
+    url(r'^sourcepackages/(.*)$', 'services.views.sourcepackage_service', name='sourcepackage_service'),
+    url(r'^opportunitylists/(.*)$', 'services.views.opportunitylist_service', name='opportunitylist_service'),
+    url(r'^opportunities/(.*)$', 'services.views.opportunity_service', name='opportunity_service'),
+    url(r'^notes/(.*)$', 'services.views.note_service', name='note_service'),
+    url(r'^actionlogentries/(.*)$', 'services.views.actionlogentry_service', name='actionlogentry_service'),
+)
+

=== added file 'harvest/services/views.py'
--- harvest/services/views.py	1970-01-01 00:00:00 +0000
+++ harvest/services/views.py	2010-08-23 14:17:40 +0000
@@ -0,0 +1,25 @@
+from opportunities.models import PackageSet, SourcePackage, OpportunityList, Opportunity, Note, ActionLogEntry
+from django.contrib.auth.models import User
+
+from services import model_service
+
+def user_service(request, url):
+    return model_service(User, request, url, include=['id', 'username', 'groups'])
+
+def packageset_service(request, url):
+    return model_service(PackageSet, request, url)
+
+def sourcepackage_service(request, url):
+    return model_service(SourcePackage, request, url)
+
+def opportunitylist_service(request, url):
+    return model_service(OpportunityList, request, url)
+
+def opportunity_service(request, url):
+    return model_service(Opportunity, request, url)
+
+def note_service(request, url):
+    return model_service(Note, request, url)
+
+def actionlogentry_service(request, url):
+    return model_service(ActionLogEntry, request, url)

=== modified file 'harvest/settings.py'
--- harvest/settings.py	2010-07-14 19:52:01 +0000
+++ harvest/settings.py	2010-08-23 14:17:40 +0000
@@ -111,6 +111,7 @@
     'django_openid_auth',
     'opportunities',
     'filters',
+    'services',
     'common',
 )
 

=== modified file 'harvest/urls.py'
--- harvest/urls.py	2009-08-26 14:57:36 +0000
+++ harvest/urls.py	2010-08-23 14:17:40 +0000
@@ -7,6 +7,7 @@
 urlpatterns = patterns('',
     url(r'^$', 'common.views.index', name='home'),
     url(r'^opportunities/', include('opportunities.urls')),
+    url(r'^services/', include('services.urls')),
     url(r'^openid/', include('django_openid_auth.urls')),
     url(r'^logout$', 'common.views.site_logout'),
     url(r'^admin/', include(admin.site.urls)),