Commit 152c385f by Sébastien Piquemal

enhanced request how-to + example

parent 714a90d7
...@@ -11,6 +11,8 @@ This enhanced request object offers the following : ...@@ -11,6 +11,8 @@ This enhanced request object offers the following :
from django.http import HttpRequest from django.http import HttpRequest
from djangorestframework.response import ErrorResponse
from djangorestframework import status
from djangorestframework.utils.mediatypes import is_form_media_type, order_by_precedence from djangorestframework.utils.mediatypes import is_form_media_type, order_by_precedence
from djangorestframework.utils import as_tuple from djangorestframework.utils import as_tuple
......
Using the enhanced request in all your views
==============================================
This example shows how you can use Django REST framework's enhanced `request` in your own views, without having to use the full-blown :class:`views.View` class.
What can it do for you ? Mostly, it will take care of parsing the request's content, and handling equally all HTTP methods ...
Before
--------
In order to support `JSON` or other serial formats, you might have parsed manually the request's content with something like : ::
class MyView(View):
def put(self, request, *args, **kwargs):
content_type = request.META['CONTENT_TYPE']
if (content_type == 'application/json'):
raw_data = request.read()
parsed_data = json.loads(raw_data)
# PLUS as many `elif` as formats you wish to support ...
# then do stuff with your data :
self.do_stuff(parsed_data['bla'], parsed_data['hoho'])
# and finally respond something
... and you were unhappy because this looks hackish.
Also, you might have tried uploading files with a PUT request - *and given up* since that's complicated to achieve even with Django 1.3.
After
------
All the dirty `Content-type` checking and content reading and parsing is done for you, and you only need to do the following : ::
class MyView(MyBaseViewUsingEnhancedRequest):
def put(self, request, *args, **kwargs):
self.do_stuff(request.DATA['bla'], request.DATA['hoho'])
# and finally respond something
So the parsed content is magically available as `.DATA` on the `request` object.
Also, if you uploaded files, they are available as `.FILES`, like with a normal POST request.
.. note:: Note that all the above is also valid for a POST request.
How to add it to your custom views ?
--------------------------------------
Now that you're convinced you need to use the enhanced request object, here is how you can add it to all your custom views : ::
from django.views.generic.base import View
from djangorestframework.mixins import RequestMixin
from djangorestframework import parsers
class MyBaseViewUsingEnhancedRequest(RequestMixin, View):
"""
Base view enabling the usage of enhanced requests with user defined views.
"""
parsers = parsers.DEFAULT_PARSERS
def dispatch(self, request, *args, **kwargs):
self.request = request
request = self.get_request()
return super(MyBaseViewUsingEnhancedRequest, self).dispatch(request, *args, **kwargs)
And then, use this class as a base for all your custom views.
.. note:: you can also check the request example.
from django.db import models
# Create your models here.
from django.conf.urls.defaults import patterns, url
from requestexample.views import RequestExampleView, MockView, EchoRequestContentView
urlpatterns = patterns('',
url(r'^$', RequestExampleView.as_view(), name='request-example'),
url(r'^content$', MockView.as_view(view_class=EchoRequestContentView), name='request-content'),
)
from djangorestframework.compat import View
from django.http import HttpResponse
from django.core.urlresolvers import reverse
from djangorestframework.mixins import RequestMixin
from djangorestframework.views import View as DRFView
from djangorestframework import parsers
class RequestExampleView(DRFView):
"""
A container view for request examples.
"""
def get(self, request):
return [{'name': 'request.DATA Example', 'url': reverse('request-content')},]
class MyBaseViewUsingEnhancedRequest(RequestMixin, View):
"""
Base view enabling the usage of enhanced requests with user defined views.
"""
parsers = parsers.DEFAULT_PARSERS
def dispatch(self, request, *args, **kwargs):
self.request = request
request = self.get_request()
return super(MyBaseViewUsingEnhancedRequest, self).dispatch(request, *args, **kwargs)
class EchoRequestContentView(MyBaseViewUsingEnhancedRequest):
"""
A view that just reads the items in `request.DATA` and echoes them back.
"""
def post(self, request, *args, **kwargs):
return HttpResponse(("Found %s in request.DATA, content : %s" %
(type(request.DATA), request.DATA)))
def put(self, request, *args, **kwargs):
return HttpResponse(("Found %s in request.DATA, content : %s" %
(type(request.DATA), request.DATA)))
class MockView(DRFView):
"""
A view that just acts as a proxy to call non-djangorestframework views, while still
displaying the browsable API interface.
"""
view_class = None
def dispatch(self, request, *args, **kwargs):
self.request = request
if self.get_request().method in ['PUT', 'POST']:
self.response = self.view_class.as_view()(request, *args, **kwargs)
return super(MockView, self).dispatch(request, *args, **kwargs)
def get(self, request, *args, **kwargs):
return
def put(self, request, *args, **kwargs):
return self.response.content
def post(self, request, *args, **kwargs):
return self.response.content
def __getattribute__(self, name):
if name == '__name__':
return self.view_class.__name__
elif name == '__doc__':
return self.view_class.__doc__
else:
return super(MockView, self).__getattribute__(name)
...@@ -23,6 +23,7 @@ class Sandbox(View): ...@@ -23,6 +23,7 @@ class Sandbox(View):
5. A code highlighting API. 5. A code highlighting API.
6. A blog posts and comments API. 6. A blog posts and comments API.
7. A basic example using permissions. 7. A basic example using permissions.
8. A basic example using enhanced request.
Please feel free to browse, create, edit and delete the resources in these examples.""" Please feel free to browse, create, edit and delete the resources in these examples."""
...@@ -33,5 +34,6 @@ class Sandbox(View): ...@@ -33,5 +34,6 @@ class Sandbox(View):
{'name': 'Object store API', 'url': reverse('object-store-root')}, {'name': 'Object store API', 'url': reverse('object-store-root')},
{'name': 'Code highlighting API', 'url': reverse('pygments-root')}, {'name': 'Code highlighting API', 'url': reverse('pygments-root')},
{'name': 'Blog posts API', 'url': reverse('blog-posts-root')}, {'name': 'Blog posts API', 'url': reverse('blog-posts-root')},
{'name': 'Permissions example', 'url': reverse('permissions-example')} {'name': 'Permissions example', 'url': reverse('permissions-example')},
{'name': 'Simple request mixin example', 'url': reverse('request-example')}
] ]
...@@ -112,6 +112,7 @@ INSTALLED_APPS = ( ...@@ -112,6 +112,7 @@ INSTALLED_APPS = (
'pygments_api', 'pygments_api',
'blogpost', 'blogpost',
'permissionsexample', 'permissionsexample',
'requestexample',
) )
import os import os
......
...@@ -11,6 +11,7 @@ urlpatterns = patterns('', ...@@ -11,6 +11,7 @@ urlpatterns = patterns('',
(r'^pygments/', include('pygments_api.urls')), (r'^pygments/', include('pygments_api.urls')),
(r'^blog-post/', include('blogpost.urls')), (r'^blog-post/', include('blogpost.urls')),
(r'^permissions-example/', include('permissionsexample.urls')), (r'^permissions-example/', include('permissionsexample.urls')),
(r'^request-example/', include('requestexample.urls')),
(r'^', include('djangorestframework.urls')), (r'^', include('djangorestframework.urls')),
) )
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment