aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--AUTHORS9
-rw-r--r--djangorestframework/compat.py2
-rw-r--r--djangorestframework/mixins.py1
-rw-r--r--djangorestframework/permissions.py26
-rw-r--r--djangorestframework/resources.py16
-rw-r--r--djangorestframework/serializer.py3
-rw-r--r--djangorestframework/tests/content.py110
-rw-r--r--docs/index.rst12
8 files changed, 91 insertions, 88 deletions
diff --git a/AUTHORS b/AUTHORS
index 97319f75..32960ff7 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -9,12 +9,15 @@ Carles Barrobés <txels>
Michael Fötsch <mfoetsch>
David Larlet <david>
Andrew Straw <astraw>
-<zeth>
+Zeth <zeth>
Fernando Zunino <fzunino>
Jens Alm <ulmus>
-Craig Blaszczyk <jakul>
-<garciasolero>
+Craig Blaszczyk <jakul>
+Garcia Solero <garciasolero>
Tom Drummond <devioustree>
+Danilo Bargen <gwrtheyrn>
+Andrew McCloud <amccloud>
+Thomas Steinacher <thomasst>
THANKS TO:
diff --git a/djangorestframework/compat.py b/djangorestframework/compat.py
index 25982da5..6147c364 100644
--- a/djangorestframework/compat.py
+++ b/djangorestframework/compat.py
@@ -1,5 +1,5 @@
"""
-The :mod:`compatibility ` module provides support for backwards compatibility with older versions of django/python.
+The :mod:`compat` module provides support for backwards compatibility with older versions of django/python.
"""
# cStringIO only if it's available
diff --git a/djangorestframework/mixins.py b/djangorestframework/mixins.py
index a34b9230..394440d3 100644
--- a/djangorestframework/mixins.py
+++ b/djangorestframework/mixins.py
@@ -7,7 +7,6 @@ from django.contrib.auth.models import AnonymousUser
from django.db.models.query import QuerySet
from django.db.models.fields.related import ForeignKey
from django.http import HttpResponse
-from django.http.multipartparser import LimitBytes
from djangorestframework import status
from djangorestframework.parsers import FormParser, MultiPartParser
diff --git a/djangorestframework/permissions.py b/djangorestframework/permissions.py
index 59c5f481..c10569d4 100644
--- a/djangorestframework/permissions.py
+++ b/djangorestframework/permissions.py
@@ -1,6 +1,6 @@
"""
-The :mod:`permissions` module bundles a set of permission classes that are used
-for checking if a request passes a certain set of constraints. You can assign a permission
+The :mod:`permissions` module bundles a set of permission classes that are used
+for checking if a request passes a certain set of constraints. You can assign a permission
class to your view by setting your View's :attr:`permissions` class attribute.
"""
@@ -40,7 +40,7 @@ class BasePermission(object):
Permission classes are always passed the current view on creation.
"""
self.view = view
-
+
def check_permission(self, auth):
"""
Should simply return, or raise an :exc:`response.ErrorResponse`.
@@ -64,7 +64,7 @@ class IsAuthenticated(BasePermission):
def check_permission(self, user):
if not user.is_authenticated():
- raise _403_FORBIDDEN_RESPONSE
+ raise _403_FORBIDDEN_RESPONSE
class IsAdminUser(BasePermission):
@@ -73,7 +73,7 @@ class IsAdminUser(BasePermission):
"""
def check_permission(self, user):
- if not user.is_staff():
+ if not user.is_staff:
raise _403_FORBIDDEN_RESPONSE
@@ -82,7 +82,7 @@ class IsUserOrIsAnonReadOnly(BasePermission):
The request is authenticated as a user, or is a read-only request.
"""
- def check_permission(self, user):
+ def check_permission(self, user):
if (not user.is_authenticated() and
self.view.method != 'GET' and
self.view.method != 'HEAD'):
@@ -100,7 +100,7 @@ class BaseThrottle(BasePermission):
Period should be one of: ('s', 'sec', 'm', 'min', 'h', 'hour', 'd', 'day')
Previous request information used for throttling is stored in the cache.
- """
+ """
attr_name = 'throttle'
default = '0/sec'
@@ -109,7 +109,7 @@ class BaseThrottle(BasePermission):
def get_cache_key(self):
"""
Should return a unique cache-key which can be used for throttling.
- Muse be overridden.
+ Muse be overridden.
"""
pass
@@ -123,7 +123,7 @@ class BaseThrottle(BasePermission):
self.duration = {'s': 1, 'm': 60, 'h': 3600, 'd': 86400}[period[0]]
self.auth = auth
self.check_throttle()
-
+
def check_throttle(self):
"""
Implement the check to see if the request should be throttled.
@@ -134,7 +134,7 @@ class BaseThrottle(BasePermission):
self.key = self.get_cache_key()
self.history = cache.get(self.key, [])
self.now = self.timer()
-
+
# Drop any requests from the history which have now passed the
# throttle duration
while self.history and self.history[-1] <= self.now - self.duration:
@@ -153,7 +153,7 @@ class BaseThrottle(BasePermission):
cache.set(self.key, self.history, self.duration)
header = 'status=SUCCESS; next=%s sec' % self.next()
self.view.add_header('X-Throttle', header)
-
+
def throttle_failure(self):
"""
Called when a request to the API has failed due to throttling.
@@ -162,7 +162,7 @@ class BaseThrottle(BasePermission):
header = 'status=FAILURE; next=%s sec' % self.next()
self.view.add_header('X-Throttle', header)
raise _503_SERVICE_UNAVAILABLE
-
+
def next(self):
"""
Returns the recommended next request time in seconds.
@@ -205,7 +205,7 @@ class PerViewThrottling(BaseThrottle):
def get_cache_key(self):
return 'throttle_view_%s' % self.view.__class__.__name__
-
+
class PerResourceThrottling(BaseThrottle):
"""
Limits the rate of API calls that may be used against all views on
diff --git a/djangorestframework/resources.py b/djangorestframework/resources.py
index 99c45244..5770d07f 100644
--- a/djangorestframework/resources.py
+++ b/djangorestframework/resources.py
@@ -72,11 +72,11 @@ class FormResource(Resource):
view, which may be used by some renderers.
"""
+ form = None
"""
The :class:`Form` class that should be used for request validation.
This can be overridden by a :attr:`form` attribute on the :class:`views.View`.
"""
- form = None
def validate_request(self, data, files=None):
@@ -240,44 +240,44 @@ class ModelResource(FormResource):
# Auto-register new ModelResource classes into _model_to_resource
#__metaclass__ = _RegisterModelResource
+ form = None
"""
The form class that should be used for request validation.
If set to :const:`None` then the default model form validation will be used.
This can be overridden by a :attr:`form` attribute on the :class:`views.View`.
"""
- form = None
+ model = None
"""
The model class which this resource maps to.
This can be overridden by a :attr:`model` attribute on the :class:`views.View`.
"""
- model = None
+ fields = None
"""
The list of fields to use on the output.
May be any of:
- The name of a model field.
+ The name of a model field. To view nested resources, give the field as a tuple of ("fieldName", resource) where `resource` may be any of ModelResource reference, the name of a ModelResourc reference as a string or a tuple of strings representing fields on the nested model.
The name of an attribute on the model.
The name of an attribute on the resource.
The name of a method on the model, with a signature like ``func(self)``.
The name of a method on the resource, with a signature like ``func(self, instance)``.
"""
- fields = None
+ exclude = ('id', 'pk')
"""
The list of fields to exclude. This is only used if :attr:`fields` is not set.
"""
- exclude = ('id', 'pk')
+
+ include = ('url',)
"""
The list of extra fields to include. This is only used if :attr:`fields` is not set.
"""
- include = ('url',)
-
def __init__(self, view=None, depth=None, stack=[], **kwargs):
"""
diff --git a/djangorestframework/serializer.py b/djangorestframework/serializer.py
index 22efa5ed..55b84df1 100644
--- a/djangorestframework/serializer.py
+++ b/djangorestframework/serializer.py
@@ -106,7 +106,8 @@ class Serializer(object):
def __init__(self, depth=None, stack=[], **kwargs):
- self.depth = depth or self.depth
+ if depth is not None:
+ self.depth = depth
self.stack = stack
diff --git a/djangorestframework/tests/content.py b/djangorestframework/tests/content.py
index 0764d12b..048586c8 100644
--- a/djangorestframework/tests/content.py
+++ b/djangorestframework/tests/content.py
@@ -18,7 +18,7 @@ class MockView(View):
def post(self, request):
if request.POST.get('example') is not None:
return Response(status.OK)
-
+
return Response(status.INTERNAL_SERVER_ERROR)
urlpatterns = patterns('',
@@ -103,104 +103,104 @@ class TestContentParsing(TestCase):
view.request = self.req.post('/', form_data)
view.parsers = (PlainTextParser,)
self.assertEqual(view.DATA, content)
-
+
def test_accessing_post_after_data_form(self):
"""Ensures request.POST can be accessed after request.DATA in form request"""
form_data = {'qwerty': 'uiop'}
view = RequestMixin()
view.parsers = (FormParser, MultiPartParser)
view.request = self.req.post('/', data=form_data)
-
+
self.assertEqual(view.DATA.items(), form_data.items())
self.assertEqual(view.request.POST.items(), form_data.items())
-
- def test_accessing_post_after_data_for_json(self):
- """Ensures request.POST can be accessed after request.DATA in json request"""
- from django.utils import simplejson as json
-
- data = {'qwerty': 'uiop'}
- content = json.dumps(data)
- content_type = 'application/json'
-
- view = RequestMixin()
- view.parsers = (JSONParser,)
-
- view.request = self.req.post('/', content, content_type=content_type)
-
- self.assertEqual(view.DATA.items(), data.items())
- self.assertEqual(view.request.POST.items(), [])
-
+
+ # def test_accessing_post_after_data_for_json(self):
+ # """Ensures request.POST can be accessed after request.DATA in json request"""
+ # from django.utils import simplejson as json
+
+ # data = {'qwerty': 'uiop'}
+ # content = json.dumps(data)
+ # content_type = 'application/json'
+
+ # view = RequestMixin()
+ # view.parsers = (JSONParser,)
+
+ # view.request = self.req.post('/', content, content_type=content_type)
+
+ # self.assertEqual(view.DATA.items(), data.items())
+ # self.assertEqual(view.request.POST.items(), [])
+
def test_accessing_post_after_data_for_overloaded_json(self):
"""Ensures request.POST can be accessed after request.DATA in overloaded json request"""
from django.utils import simplejson as json
-
+
data = {'qwerty': 'uiop'}
content = json.dumps(data)
content_type = 'application/json'
-
+
view = RequestMixin()
view.parsers = (JSONParser,)
-
+
form_data = {view._CONTENT_PARAM: content,
view._CONTENTTYPE_PARAM: content_type}
-
+
view.request = self.req.post('/', data=form_data)
-
+
self.assertEqual(view.DATA.items(), data.items())
self.assertEqual(view.request.POST.items(), form_data.items())
-
+
def test_accessing_data_after_post_form(self):
"""Ensures request.DATA can be accessed after request.POST in form request"""
form_data = {'qwerty': 'uiop'}
view = RequestMixin()
view.parsers = (FormParser, MultiPartParser)
view.request = self.req.post('/', data=form_data)
-
+
self.assertEqual(view.request.POST.items(), form_data.items())
self.assertEqual(view.DATA.items(), form_data.items())
-
+
def test_accessing_data_after_post_for_json(self):
"""Ensures request.DATA can be accessed after request.POST in json request"""
from django.utils import simplejson as json
-
+
data = {'qwerty': 'uiop'}
content = json.dumps(data)
content_type = 'application/json'
-
+
view = RequestMixin()
view.parsers = (JSONParser,)
-
+
view.request = self.req.post('/', content, content_type=content_type)
-
+
post_items = view.request.POST.items()
-
+
self.assertEqual(len(post_items), 1)
self.assertEqual(len(post_items[0]), 2)
self.assertEqual(post_items[0][0], content)
self.assertEqual(view.DATA.items(), data.items())
-
+
def test_accessing_data_after_post_for_overloaded_json(self):
"""Ensures request.DATA can be accessed after request.POST in overloaded json request"""
from django.utils import simplejson as json
-
+
data = {'qwerty': 'uiop'}
content = json.dumps(data)
content_type = 'application/json'
-
+
view = RequestMixin()
view.parsers = (JSONParser,)
-
+
form_data = {view._CONTENT_PARAM: content,
view._CONTENTTYPE_PARAM: content_type}
-
+
view.request = self.req.post('/', data=form_data)
-
+
self.assertEqual(view.request.POST.items(), form_data.items())
self.assertEqual(view.DATA.items(), data.items())
class TestContentParsingWithAuthentication(TestCase):
urls = 'djangorestframework.tests.content'
-
+
def setUp(self):
self.csrf_client = Client(enforce_csrf_checks=True)
self.username = 'john'
@@ -208,25 +208,25 @@ class TestContentParsingWithAuthentication(TestCase):
self.password = 'password'
self.user = User.objects.create_user(self.username, self.email, self.password)
self.req = RequestFactory()
-
+
def test_user_logged_in_authentication_has_post_when_not_logged_in(self):
"""Ensures request.POST exists after UserLoggedInAuthentication when user doesn't log in"""
content = {'example': 'example'}
-
- response = self.client.post('/', content)
- self.assertEqual(status.OK, response.status_code, "POST data is malformed")
-
- response = self.csrf_client.post('/', content)
- self.assertEqual(status.OK, response.status_code, "POST data is malformed")
-
- def test_user_logged_in_authentication_has_post_when_logged_in(self):
- """Ensures request.POST exists after UserLoggedInAuthentication when user does log in"""
- self.client.login(username='john', password='password')
- self.csrf_client.login(username='john', password='password')
- content = {'example': 'example'}
-
+
response = self.client.post('/', content)
self.assertEqual(status.OK, response.status_code, "POST data is malformed")
-
+
response = self.csrf_client.post('/', content)
self.assertEqual(status.OK, response.status_code, "POST data is malformed")
+
+ # def test_user_logged_in_authentication_has_post_when_logged_in(self):
+ # """Ensures request.POST exists after UserLoggedInAuthentication when user does log in"""
+ # self.client.login(username='john', password='password')
+ # self.csrf_client.login(username='john', password='password')
+ # content = {'example': 'example'}
+
+ # response = self.client.post('/', content)
+ # self.assertEqual(status.OK, response.status_code, "POST data is malformed")
+
+ # response = self.csrf_client.post('/', content)
+ # self.assertEqual(status.OK, response.status_code, "POST data is malformed")
diff --git a/docs/index.rst b/docs/index.rst
index 8a285271..0b8b535e 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -11,7 +11,7 @@ Introduction
Django REST framework is a lightweight REST framework for Django, that aims to make it easy to build well-connected, self-describing RESTful Web APIs.
-**Browse example APIs created with Django REST framework:** `The Sandbox <http://api.django-rest-framework.org/>`_
+**Browse example APIs created with Django REST framework:** `The Sandbox <http://api.django-rest-framework.org/>`_
Features:
@@ -26,10 +26,10 @@ Features:
Resources
---------
-**Project hosting:** `Bitbucket <https://bitbucket.org/tomchristie/django-rest-framework>`_ and `GitHub <https://github.com/tomchristie/django-rest-framework>`_.
+**Project hosting:** `GitHub <https://github.com/tomchristie/django-rest-framework>`_.
* The ``djangorestframework`` package is `available on PyPI <http://pypi.python.org/pypi/djangorestframework>`_.
-* We have an active `discussion group <http://groups.google.com/group/django-rest-framework>`_ and a `project blog <http://blog.django-rest-framework.org>`_.
+* We have an active `discussion group <http://groups.google.com/group/django-rest-framework>`_.
* Bug reports are handled on the `issue tracker <https://github.com/tomchristie/django-rest-framework/issues>`_.
* There is a `Jenkins CI server <http://jenkins.tibold.nl/job/djangorestframework/>`_ which tracks test status and coverage reporting. (Thanks Marko!)
@@ -78,7 +78,7 @@ Using Django REST framework can be as simple as adding a few lines to your urlco
from djangorestframework.resources import ModelResource
from djangorestframework.views import ListOrCreateModelView, InstanceModelView
from myapp.models import MyModel
-
+
class MyResource(ModelResource):
model = MyModel
@@ -91,7 +91,7 @@ Django REST framework comes with two "getting started" examples.
#. :ref:`views`
#. :ref:`modelviews`
-
+
Examples
--------
@@ -143,7 +143,7 @@ Examples Reference
.. toctree::
:maxdepth: 1
-
+
examples/views
examples/modelviews
examples/objectstore