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.
Will Larson
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].__name__.split("Responder")[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(format, subset),
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(format, subset))
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(format, subset))
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(format, subset))
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, format, subset):
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