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

Proposed by Daniel Holbach
Status: Merged
Merged at revision: 244
Proposed branch: lp:~dholbach/harvest/581730
Merge into: lp:harvest
Diff against target: 231 lines (+194/-0)
5 files modified
harvest/services/__init__.py (+155/-0)
harvest/services/urls.py (+12/-0)
harvest/services/views.py (+25/-0)
harvest/settings.py (+1/-0)
harvest/urls.py (+1/-0)
To merge this branch: bzr merge lp:~dholbach/harvest/581730
Reviewer Review Type Date Requested Status
James Westby Approve
Review via email: mp+33387@code.launchpad.net
To post a comment you must log in.
Revision history for this message
James Westby (james-w) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== 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:42 +0000
@@ -0,0 +1,155 @@
1# Portions of this code comes from the Oct09 project
2# developed by the Moffitt Cancer Center.
3# License: http://bitbucket.org/oct09/main/src/tip/COPYING
4# Project: http://bitbucket.org/oct09/main/wiki/Home
5
6from django.db.models import Model
7from django.http import HttpResponse
8from django.forms.fields import EMPTY_VALUES
9from django.utils import simplejson
10import re
11import decimal
12
13CHUNK_SIZE = 500
14
15def parse_number_argument(arguments, which):
16 if not arguments.has_key(which):
17 return None
18 if arguments[which] in EMPTY_VALUES:
19 return None
20 try:
21 number = int(arguments[which])
22 except:
23 number = None
24 return number
25
26def model_service(model, request, url, include=None, exclude=None):
27 (instance_id, rem_url) = get_model_id(request, url)
28
29 try:
30 if instance_id is not None and instance_id != '':
31 return model_entity(model, request, url, include, exclude)
32 else:
33 return model_collection(model, request, url, include, exclude)
34 except Exception, e:
35 return HttpResponse(encode_error(e))
36
37def model_entity(model, request, url, include=None, exclude=None):
38 (entity_id, rem_url) = get_model_id(request, url)
39
40 try:
41 entity = model.objects.get(pk=entity_id)
42 except:
43 return HttpResponse(encode_error("Entity not found"))
44
45
46 # Otherwise process the entity request
47 if request.method == "GET":
48 return HttpResponse(encode(entity, include, exclude), mimetype=get_mimetype())
49
50 elif request.method == "PUT":
51 return HttpResponse(encode_error("Write operations are not supported"))
52
53 elif request.method == "DELETE":
54 return HttpResponse(encode_error("Write operations are not supported"))
55
56 return HttpResponse(encode_error("%s Not Implemented"%request.method))
57
58def model_collection(model, request, url, include=None, exclude=None):
59 if request.method == "GET":
60 results = do_search(model, request.GET, include, exclude)
61
62 collection = list(results)
63 return HttpResponse(encode(collection, include, exclude), mimetype=get_mimetype())
64
65 elif request.method == "POST":
66 return HttpResponse(encode_error("Write operations are not supported"))
67
68 return HttpResponse(encode_error("%s Not Implemented"%request.method))
69
70def do_search(model, request, include=None, exclude=None):
71 search_fields = include
72 if search_fields is None:
73 search_fields = [f.name for f in model._meta.local_fields+model._meta.many_to_many if not f.name.endswith("_ptr")]
74 if exclude is not None:
75 search_fields = [f for f in search_fields if f not in exclude]
76 search_values = dict([(str(key), value) for (key, value) in request.items()])
77
78 extra_arguments = {}
79 for key in search_values.keys():
80 if key.startswith('_'):
81 extra_arguments[key] = search_values.pop(key)
82 offset = parse_number_argument(extra_arguments, '_offset')
83 length = parse_number_argument(extra_arguments, '_length')
84 if not length or length > CHUNK_SIZE:
85 length = CHUNK_SIZE
86 results = model.objects.filter(**search_values)[offset:length]
87
88 if '_sortby' in request and request['_sortby'] not in EMPTY_VALUES:
89 results = results.order_by(request.get('_sortby'))
90 return results
91
92def get_model_id(request, url):
93 instance_id = None
94 rem_url = None
95 if url is not None and len(url) > 0:
96 m = re.match(r"^([^/]+)/?(.*)", url)
97
98 if m is not None:
99 instance_id = m.group(1)
100 rem_url = m.group(2)
101 return (instance_id, rem_url)
102
103def encode(entity, include=None, exclude=None):
104 json = JSONEncoder(include, exclude)
105 return json.encode(entity)
106
107def decode(klass, entity, request, url=None):
108 return request.raw_post_data
109
110def get_mimetype():
111 return "application/json"
112
113def encode_error(error):
114 json = JSONEncoder()
115 return json.encode({'error': unicode(error)})
116
117class JSONEncoder(simplejson.JSONEncoder):
118
119 def __init__(self, include=None, exclude=None):
120 self.include = include
121 self.exclude = exclude
122 super(JSONEncoder, self).__init__()
123
124 def get_field_value(self, o, field):
125 f = getattr(o, field)
126 try:
127 if isinstance(f, Model):
128 if hasattr(f, 'pk'):
129 return self.default(f.pk)
130 else:
131 return None
132 if isinstance(f, decimal.Decimal):
133 return o._meta.get_field_by_name(field)[0]._format(f)
134 else:
135 return self.default(f)
136 except Exception:
137 return None
138
139 def default(self, o=None):
140
141 if isinstance(o, Model):
142 model_fields = self.include
143 if model_fields is None:
144 model_fields = [f.name for f in o._meta.fields+o._meta.many_to_many if not f.name.endswith("_ptr")]
145 if self.exclude is not None:
146 model_fields = [f for f in model_fields if f not in self.exclude]
147 d = dict([(field, self.get_field_value(o, field)) for field in model_fields])
148 return d
149 elif o.__class__.__name__ == 'ManyRelatedManager' or o.__class__.__name__ == 'RelatedManager':
150 return [r.pk for r in o.all()]
151 elif isinstance(o, (int, long, float)):
152 return o
153 elif o is None:
154 return None
155 return str(o)
0156
=== 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:42 +0000
@@ -0,0 +1,12 @@
1from django.conf.urls.defaults import *
2
3urlpatterns = patterns('',
4 url(r'^users/(.*)$', 'services.views.user_service', name='user_service'),
5 url(r'^packagesets/(.*)$', 'services.views.packageset_service', name='packageset_service'),
6 url(r'^sourcepackages/(.*)$', 'services.views.sourcepackage_service', name='sourcepackage_service'),
7 url(r'^opportunitylists/(.*)$', 'services.views.opportunitylist_service', name='opportunitylist_service'),
8 url(r'^opportunities/(.*)$', 'services.views.opportunity_service', name='opportunity_service'),
9 url(r'^notes/(.*)$', 'services.views.note_service', name='note_service'),
10 url(r'^actionlogentries/(.*)$', 'services.views.actionlogentry_service', name='actionlogentry_service'),
11)
12
013
=== 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:42 +0000
@@ -0,0 +1,25 @@
1from opportunities.models import PackageSet, SourcePackage, OpportunityList, Opportunity, Note, ActionLogEntry
2from django.contrib.auth.models import User
3
4from services import model_service
5
6def user_service(request, url):
7 return model_service(User, request, url, include=['id', 'username', 'groups'])
8
9def packageset_service(request, url):
10 return model_service(PackageSet, request, url)
11
12def sourcepackage_service(request, url):
13 return model_service(SourcePackage, request, url)
14
15def opportunitylist_service(request, url):
16 return model_service(OpportunityList, request, url)
17
18def opportunity_service(request, url):
19 return model_service(Opportunity, request, url)
20
21def note_service(request, url):
22 return model_service(Note, request, url)
23
24def actionlogentry_service(request, url):
25 return model_service(ActionLogEntry, request, url)
026
=== modified file 'harvest/settings.py'
--- harvest/settings.py 2010-07-14 19:52:01 +0000
+++ harvest/settings.py 2010-08-23 14:17:42 +0000
@@ -111,6 +111,7 @@
111 'django_openid_auth',111 'django_openid_auth',
112 'opportunities',112 'opportunities',
113 'filters',113 'filters',
114 'services',
114 'common',115 'common',
115)116)
116117
117118
=== modified file 'harvest/urls.py'
--- harvest/urls.py 2009-08-26 14:57:36 +0000
+++ harvest/urls.py 2010-08-23 14:17:42 +0000
@@ -7,6 +7,7 @@
7urlpatterns = patterns('',7urlpatterns = patterns('',
8 url(r'^$', 'common.views.index', name='home'),8 url(r'^$', 'common.views.index', name='home'),
9 url(r'^opportunities/', include('opportunities.urls')),9 url(r'^opportunities/', include('opportunities.urls')),
10 url(r'^services/', include('services.urls')),
10 url(r'^openid/', include('django_openid_auth.urls')),11 url(r'^openid/', include('django_openid_auth.urls')),
11 url(r'^logout$', 'common.views.site_logout'),12 url(r'^logout$', 'common.views.site_logout'),
12 url(r'^admin/', include(admin.site.urls)),13 url(r'^admin/', include(admin.site.urls)),

Subscribers

People subscribed via source and target branches

to all changes: