root / ui / userdata / rest.py @ 26bade45
History | View | Annotate | Download (6.3 kB)
1 |
from django import http |
---|---|
2 |
from django.template import RequestContext, loader |
3 |
from django.utils import simplejson as json |
4 |
from django.core import serializers |
5 |
from django.core.urlresolvers import reverse |
6 |
|
7 |
# base view class
|
8 |
# https://github.com/bfirsh/django-class-based-views/blob/master/class_based_views/base.py
|
9 |
class View(object): |
10 |
"""
|
11 |
Intentionally simple parent class for all views. Only implements
|
12 |
dispatch-by-method and simple sanity checking.
|
13 |
"""
|
14 |
|
15 |
method_names = ['GET', 'POST', 'DELETE', 'HEAD', 'OPTIONS', 'TRACE'] |
16 |
|
17 |
def __init__(self, *args, **kwargs): |
18 |
"""
|
19 |
Constructor. Called in the URLconf; can contain helpful extra
|
20 |
keyword arguments, and other things.
|
21 |
"""
|
22 |
# Go through keyword arguments, and either save their values to our
|
23 |
# instance, or raise an error.
|
24 |
for key, value in kwargs.items(): |
25 |
if key in self.method_names: |
26 |
raise TypeError(u"You tried to pass in the %s method name as a " |
27 |
u"keyword argument to %s(). Don't do that."
|
28 |
% (key, self.__class__.__name__))
|
29 |
if hasattr(self, key): |
30 |
setattr(self, key, value) |
31 |
else:
|
32 |
raise TypeError(u"%s() received an invalid keyword %r" % ( |
33 |
self.__class__.__name__,
|
34 |
key, |
35 |
)) |
36 |
|
37 |
@classmethod
|
38 |
def as_view(cls, *initargs, **initkwargs): |
39 |
"""
|
40 |
Main entry point for a request-response process.
|
41 |
"""
|
42 |
def view(request, *args, **kwargs): |
43 |
self = cls(*initargs, **initkwargs)
|
44 |
return self.dispatch(request, *args, **kwargs) |
45 |
return view
|
46 |
|
47 |
def dispatch(self, request, *args, **kwargs): |
48 |
# Try to dispatch to the right method for that; if it doesn't exist,
|
49 |
# raise a big error.
|
50 |
if hasattr(self, request.method.upper()): |
51 |
self.request = request
|
52 |
self.args = args
|
53 |
self.kwargs = kwargs
|
54 |
data = request.raw_post_data |
55 |
|
56 |
if request.method.upper() in ['POST', 'PUT']: |
57 |
# Expect json data
|
58 |
if request.META.get('CONTENT_TYPE').startswith('application/json'): |
59 |
try:
|
60 |
data = json.loads(data) |
61 |
except ValueError: |
62 |
raise http.HttpResponseServerError('Invalid JSON data.') |
63 |
else:
|
64 |
raise http.HttpResponseServerError('Unsupported Content-Type.') |
65 |
|
66 |
return getattr(self, request.method.upper())(request, data, *args, **kwargs) |
67 |
else:
|
68 |
allowed_methods = [m for m in self.method_names if hasattr(self, m)] |
69 |
return http.HttpResponseNotAllowed(allowed_methods)
|
70 |
|
71 |
class JSONRestView(View): |
72 |
"""
|
73 |
Class that provides helpers to produce a json response
|
74 |
"""
|
75 |
|
76 |
url_name = None
|
77 |
def __init__(self, url_name, *args, **kwargs): |
78 |
self.url_name = url_name
|
79 |
return super(JSONRestView, self).__init__(*args, **kwargs) |
80 |
|
81 |
def update_instance(self, i, data, exclude_fields=[]): |
82 |
update_keys = data.keys() |
83 |
for field in i._meta.get_all_field_names(): |
84 |
if field in update_keys and (field not in exclude_fields): |
85 |
i.__setattr__(field, data[field]) |
86 |
|
87 |
return i
|
88 |
|
89 |
def instance_to_dict(self, i, exclude_fields=[]): |
90 |
"""
|
91 |
Convert model instance to python dict
|
92 |
"""
|
93 |
d = {} |
94 |
d['uri'] = reverse(self.url_name, kwargs={'id': i.pk}) |
95 |
|
96 |
for field in i._meta.get_all_field_names(): |
97 |
if field in exclude_fields: |
98 |
continue
|
99 |
|
100 |
d[field] = i.__getattribute__(field) |
101 |
return d
|
102 |
|
103 |
def qs_to_dict_iter(self, qs, exclude_fields=[]): |
104 |
"""
|
105 |
Convert queryset to an iterator of model instances dicts
|
106 |
"""
|
107 |
for i in qs: |
108 |
yield self.instance_to_dict(i, exclude_fields) |
109 |
|
110 |
def json_response(self, data): |
111 |
return http.HttpResponse(json.dumps(data), mimetype="application/json") |
112 |
|
113 |
class ResourceView(JSONRestView): |
114 |
method_names = ['GET', 'POST', 'PUT', 'DELETE'] |
115 |
|
116 |
model = None
|
117 |
exclude_fields = [] |
118 |
|
119 |
def queryset(self): |
120 |
return self.model.objects.all() |
121 |
|
122 |
def instance(self): |
123 |
"""
|
124 |
Retrieve selected instance based on url parameter
|
125 |
|
126 |
id parameter should be set in urlpatterns expression
|
127 |
"""
|
128 |
try:
|
129 |
return self.queryset().get(pk=self.kwargs.get("id")) |
130 |
except self.model.DoesNotExist: |
131 |
raise http.Http404
|
132 |
|
133 |
def GET(self, request, data, *args, **kwargs): |
134 |
return self.json_response(self.instance_to_dict(self.instance(), |
135 |
self.exclude_fields))
|
136 |
|
137 |
def PUT(self, request, data, *args, **kwargs): |
138 |
instance = self.instance()
|
139 |
self.update_instance(instance, data, self.exclude_fields) |
140 |
instance.save() |
141 |
return self.GET(request, data, *args, **kwargs) |
142 |
|
143 |
def DELETE(self, request, data, *args, **kwargs): |
144 |
self.instance().delete()
|
145 |
return self.json_response("") |
146 |
|
147 |
|
148 |
class CollectionView(JSONRestView): |
149 |
method_names = ['GET', 'POST'] |
150 |
|
151 |
model = None
|
152 |
exclude_fields = [] |
153 |
|
154 |
def queryset(self): |
155 |
return self.model.objects.all() |
156 |
|
157 |
def GET(self, request, data, *args, **kwargs): |
158 |
return self.json_response(list(self.qs_to_dict_iter(self.queryset(), |
159 |
self.exclude_fields)))
|
160 |
|
161 |
def POST(self, request, data, *args, **kwargs): |
162 |
instance = self.model()
|
163 |
self.update_instance(instance, data, self.exclude_fields) |
164 |
instance.save() |
165 |
return self.json_response(self.instance_to_dict(instance, |
166 |
self.exclude_fields))
|
167 |
|
168 |
class UserResourceView(ResourceView): |
169 |
"""
|
170 |
Filter resource queryset for request user entries
|
171 |
"""
|
172 |
def queryset(self): |
173 |
return super(UserResourceView, |
174 |
self).queryset().filter(user=self.request.user) |
175 |
|
176 |
class UserCollectionView(CollectionView): |
177 |
"""
|
178 |
Filter collection queryset for request user entries
|
179 |
"""
|
180 |
def queryset(self): |
181 |
return super(UserCollectionView, self).queryset().filter(user=self.request.user) |
182 |
|
183 |
def POST(self, request, data, *args, **kwargs): |
184 |
instance = self.model()
|
185 |
self.update_instance(instance, data, self.exclude_fields) |
186 |
instance.user = request.user |
187 |
instance.save() |
188 |
return self.json_response(self.instance_to_dict(instance, |
189 |
self.exclude_fields))
|
190 |
|