david / django-modelviews
Backup of an old repository with useful ideas. Initial goal: integrating REST to django admin (class-based views).
Clone this repository (size: 85.8 KB): HTTPS / SSH
$ hg clone http://code.welldev.org/django-modelviews
| commit 49: | 98cde33c57b2 |
| parent 48: | b31a15f01c89 |
| branch: | default |
Can now dictate Responder to use by setting the appropriate mimetype.
Also added tests.
2 years ago
Changed (Δ1.8 KB):
raw changeset »
generic/rest_views.py (28 lines added, 14 lines removed)
tests/test_modelview/tests.py (31 lines added, 0 lines removed)
Up to file-list generic/rest_views.py:
| … | … | @@ -88,7 +88,7 @@ class ModelView(BaseView): |
88 |
88 |
self.post_save_redirect = post_save_redirect |
89 |
89 |
self.paginate_by = paginate_by |
90 |
90 |
self.allow_empty = allow_empty |
91 |
self.default_responder = responders[0] |
|
91 |
self.default_responder = responders[0] |
|
92 |
92 |
self.responders = dict((responder.__name__, responder) for responder in responders) |
93 |
93 |
if isinstance(methods, tuple): |
94 |
94 |
self.methods = dict(zip(methods, len(methods)*(False,))) |
| … | … | @@ -111,27 +111,19 @@ class ModelView(BaseView): |
111 |
111 |
if not self.methods[request_method](request, **kwargs): |
112 |
112 |
return HttpResponseNotAllowed(request_method) |
113 |
113 |
|
114 |
# Unmatched regex groups in the url will not recieve |
|
115 |
# the default value specified for the method, but |
|
116 |
# instead recieve the value None. Thus we must |
|
117 |
# explicitly check for None and assign the desired |
|
118 |
# value if we want default values. |
|
119 |
if format is None: |
|
120 |
format = self.default_responder |
|
121 |
||
122 |
114 |
# Filter initial queryset given request arguments. |
123 |
115 |
subset = self.get_subset(request, object_pk, slug, **kwargs) |
124 |
116 |
|
125 |
117 |
# Dispatch |
126 |
118 |
if request_method == 'GET': |
127 |
return self.read(request, subset, self.get_responder( |
|
119 |
return self.read(request, subset, self.get_responder(request, format, subset), |
|
128 |
120 |
is_list=object_pk is None and slug is None) |
129 |
121 |
elif request_method == 'POST': |
130 |
return self.create(request, self.get_responder( |
|
122 |
return self.create(request, self.get_responder(request, format, subset)) |
|
131 |
123 |
elif request_method == 'PUT': |
132 |
return self.update(request, subset[0], self.get_responder( |
|
124 |
return self.update(request, subset[0], self.get_responder(request, format, subset)) |
|
133 |
125 |
elif request_method == 'DELETE': |
134 |
return self.delete(request, subset[0], self.get_responder( |
|
126 |
return self.delete(request, subset[0], self.get_responder(request, format, subset)) |
|
135 |
127 |
else: |
136 |
128 |
raise Http404 |
137 |
129 |
|
| … | … | @@ -153,10 +145,23 @@ class ModelView(BaseView): |
153 |
145 |
lookup_kwargs[self.slug_field] = slug |
154 |
146 |
return self.get_query_set(request).filter(**lookup_kwargs) |
155 |
147 |
|
156 |
def get_responder(self, |
|
148 |
def get_responder(self, request, format, subset): |
|
157 |
149 |
""" |
158 |
150 |
Returns a ``Responder`` instance given the format. |
151 |
If no format is given, then attempt to find an |
|
152 |
appropriate ``Responder`` by mimetype, and finally |
|
153 |
resort to the default ``Responder`` if needed. |
|
159 |
154 |
""" |
155 |
# Attempt to detect formatter by mimetype. |
|
156 |
if format is None: |
|
157 |
responder = self.get_responder_by_mimetype(request) |
|
158 |
if responder is not None: |
|
159 |
return responder(subset) |
|
160 |
||
161 |
# Fallback on default formatter. |
|
162 |
if format is None: |
|
163 |
return self.default_responder(subset) |
|
164 |
||
160 |
165 |
try: |
161 |
166 |
# get_query_set requires a request parameter, but doesn't |
162 |
167 |
# do anything with the parameter (presumably a subclass |
| … | … | @@ -165,6 +170,15 @@ class ModelView(BaseView): |
165 |
170 |
except KeyError: |
166 |
171 |
raise ImproperlyConfigured("%s responder doesn't exist." % '%sResponder' % format.title()) |
167 |
172 |
|
173 |
def get_responder_by_mimetype(self,request): |
|
174 |
if request.META.has_key('CONTENT_TYPE'): |
|
175 |
mimetype = request.META['CONTENT_TYPE'].lower() |
|
176 |
for responder in self.responders.itervalues(): |
|
177 |
if mimetype.startswith(responder.mimetype): |
|
178 |
return responder |
|
179 |
||
180 |
||
181 |
||
168 |
182 |
def get_form(self, request): |
169 |
183 |
""" |
170 |
184 |
Returns a ``ModelForm`` class to be used in this view. |
Up to file-list tests/test_modelview/tests.py:
| … | … | @@ -250,3 +250,34 @@ class ModelViewTest(TestCase): |
250 |
250 |
self.assertNotEqual(response.content.find(david_comment.content), -1) |
251 |
251 |
self.assertEqual(response.content.find(will_comment.content), -1) |
252 |
252 |
|
253 |
||
254 |
def test_detecting_responder_by_mimetype(self): |
|
255 |
a = Article.objects.all()[0] |
|
256 |
||
257 |
# test 'text/html' |
|
258 |
response = self.client.get('/articles/%s/' % a.slug, CONTENT_TYPE='text/html') |
|
259 |
self.assertEqual(response.status_code, 200) |
|
260 |
self.assertTemplateUsed(response, 'test_modelview/article_detail.html') |
|
261 |
||
262 |
# 'application/json' |
|
263 |
response = self.client.get('/articles/%s/' % a.slug, CONTENT_TYPE='application/json') |
|
264 |
self.assertEqual(response.status_code, 200) |
|
265 |
data = simplejson.loads(response.content) |
|
266 |
self.assertEqual(data[0]['fields']['slug'], a.slug) |
|
267 |
self.assertEqual(data[0]['pk'], a.pk) |
|
268 |
self.assertEqual(data[0]['fields']['body'], a.body) |
|
269 |
||
270 |
# 'application/xml' |
|
271 |
response = self.client.get('/articles/%s/' % a.slug, CONTENT_TYPE='application/xml') |
|
272 |
self.assertEqual(response.status_code, 200) |
|
273 |
||
274 |
# 'text/yaml' |
|
275 |
try: |
|
276 |
import yaml |
|
277 |
response = self.client.get('/articles/%s/' % a.slug, CONTENT_TYPE='text/yaml') |
|
278 |
self.assertEqual(response.status_code, 200) |
|
279 |
data = yaml.load(response.content)[0] |
|
280 |
self.assertEqual(a.slug, data['fields']['slug']) |
|
281 |
self.assertEqual(a.body, data['fields']['body']) |
|
282 |
except ImportError: |
|
283 |
pass |
