mirror of
https://github.com/encode/django-rest-framework.git
synced 2024-12-01 14:04:02 +03:00
Merge with 4b1ee62051cce8fa9b83ac740d7262ad4a55494b
This commit is contained in:
commit
209ee82903
|
@ -67,6 +67,14 @@ except ImportError:
|
||||||
# django.views.generic.View (Django >= 1.3)
|
# django.views.generic.View (Django >= 1.3)
|
||||||
try:
|
try:
|
||||||
from django.views.generic import View
|
from django.views.generic import View
|
||||||
|
if not hasattr(View, 'head'):
|
||||||
|
# First implementation of Django class-based views did not include head method
|
||||||
|
# in base View class - https://code.djangoproject.com/ticket/15668
|
||||||
|
class ViewPlusHead(View):
|
||||||
|
def head(self, request, *args, **kwargs):
|
||||||
|
return self.get(request, *args, **kwargs)
|
||||||
|
View = ViewPlusHead
|
||||||
|
|
||||||
except ImportError:
|
except ImportError:
|
||||||
from django import http
|
from django import http
|
||||||
from django.utils.functional import update_wrapper
|
from django.utils.functional import update_wrapper
|
||||||
|
@ -145,6 +153,8 @@ except ImportError:
|
||||||
#)
|
#)
|
||||||
return http.HttpResponseNotAllowed(allowed_methods)
|
return http.HttpResponseNotAllowed(allowed_methods)
|
||||||
|
|
||||||
|
def head(self, request, *args, **kwargs):
|
||||||
|
return self.get(request, *args, **kwargs)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import markdown
|
import markdown
|
||||||
|
|
|
@ -17,6 +17,7 @@ from djangorestframework.utils import dict2xml, url_resolves
|
||||||
from djangorestframework.utils.breadcrumbs import get_breadcrumbs
|
from djangorestframework.utils.breadcrumbs import get_breadcrumbs
|
||||||
from djangorestframework.utils.description import get_name, get_description
|
from djangorestframework.utils.description import get_name, get_description
|
||||||
from djangorestframework.utils.mediatypes import get_media_type_params, add_media_type_param, media_type_matches
|
from djangorestframework.utils.mediatypes import get_media_type_params, add_media_type_param, media_type_matches
|
||||||
|
from djangorestframework import VERSION
|
||||||
|
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
import re
|
import re
|
||||||
|
@ -285,6 +286,7 @@ class DocumentingTemplateRenderer(BaseRenderer):
|
||||||
'response': self.view.response,
|
'response': self.view.response,
|
||||||
'description': description,
|
'description': description,
|
||||||
'name': name,
|
'name': name,
|
||||||
|
'version': VERSION,
|
||||||
'markeddown': markeddown,
|
'markeddown': markeddown,
|
||||||
'breadcrumblist': breadcrumb_list,
|
'breadcrumblist': breadcrumb_list,
|
||||||
'available_media_types': self.view._rendered_media_types,
|
'available_media_types': self.view._rendered_media_types,
|
||||||
|
|
|
@ -6,7 +6,7 @@ from django.db.models.fields.related import RelatedField
|
||||||
from django.utils.encoding import smart_unicode
|
from django.utils.encoding import smart_unicode
|
||||||
|
|
||||||
from djangorestframework.response import ErrorResponse
|
from djangorestframework.response import ErrorResponse
|
||||||
from djangorestframework.serializer import Serializer
|
from djangorestframework.serializer import Serializer, _SkipField
|
||||||
from djangorestframework.utils import as_tuple
|
from djangorestframework.utils import as_tuple
|
||||||
|
|
||||||
import decimal
|
import decimal
|
||||||
|
@ -342,7 +342,7 @@ class ModelResource(FormResource):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if not hasattr(self, 'view_callable'):
|
if not hasattr(self, 'view_callable'):
|
||||||
raise NoReverseMatch
|
raise _SkipField
|
||||||
|
|
||||||
# dis does teh magicks...
|
# dis does teh magicks...
|
||||||
urlconf = get_urlconf()
|
urlconf = get_urlconf()
|
||||||
|
@ -371,7 +371,7 @@ class ModelResource(FormResource):
|
||||||
return reverse(self.view_callable[0], kwargs=instance_attrs)
|
return reverse(self.view_callable[0], kwargs=instance_attrs)
|
||||||
except NoReverseMatch:
|
except NoReverseMatch:
|
||||||
pass
|
pass
|
||||||
raise NoReverseMatch
|
raise _SkipField
|
||||||
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
|
|
@ -16,13 +16,13 @@ class Response(object):
|
||||||
An HttpResponse that may include content that hasn't yet been serialized.
|
An HttpResponse that may include content that hasn't yet been serialized.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, status=200, content=None, headers={}):
|
def __init__(self, status=200, content=None, headers=None):
|
||||||
self.status = status
|
self.status = status
|
||||||
self.media_type = None
|
self.media_type = None
|
||||||
self.has_content_body = content is not None
|
self.has_content_body = content is not None
|
||||||
self.raw_content = content # content prior to filtering
|
self.raw_content = content # content prior to filtering
|
||||||
self.cleaned_content = content # content after filtering
|
self.cleaned_content = content # content after filtering
|
||||||
self.headers = headers
|
self.headers = headers or {}
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def status_text(self):
|
def status_text(self):
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
|
|
||||||
<div id="header">
|
<div id="header">
|
||||||
<div id="branding">
|
<div id="branding">
|
||||||
<h1 id="site-name"><a href='http://django-rest-framework.org'>Django REST framework</a></h1>
|
<h1 id="site-name"><a href='http://django-rest-framework.org'>Django REST framework</a> <small>{{ version }}</small></h1>
|
||||||
</div>
|
</div>
|
||||||
<div id="user-tools">
|
<div id="user-tools">
|
||||||
{% if user.is_active %}Welcome, {{ user }}.{% if logout_url %} <a href='{{ logout_url }}'>Log out</a>{% endif %}{% else %}Anonymous {% if login_url %}<a href='{{ login_url }}'>Log in</a>{% endif %}{% endif %}
|
{% if user.is_active %}Welcome, {{ user }}.{% if logout_url %} <a href='{{ logout_url }}'>Log out</a>{% endif %}{% else %}Anonymous {% if login_url %}<a href='{{ login_url }}'>Log in</a>{% endif %}{% endif %}
|
||||||
|
|
|
@ -6,7 +6,6 @@ from djangorestframework.compat import RequestFactory
|
||||||
from djangorestframework.mixins import RequestMixin
|
from djangorestframework.mixins import RequestMixin
|
||||||
from djangorestframework.parsers import FormParser, MultiPartParser, PlainTextParser
|
from djangorestframework.parsers import FormParser, MultiPartParser, PlainTextParser
|
||||||
|
|
||||||
|
|
||||||
class TestContentParsing(TestCase):
|
class TestContentParsing(TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.req = RequestFactory()
|
self.req = RequestFactory()
|
||||||
|
@ -16,6 +15,11 @@ class TestContentParsing(TestCase):
|
||||||
view.request = self.req.get('/')
|
view.request = self.req.get('/')
|
||||||
self.assertEqual(view.DATA, None)
|
self.assertEqual(view.DATA, None)
|
||||||
|
|
||||||
|
def ensure_determines_no_content_HEAD(self, view):
|
||||||
|
"""Ensure view.DATA returns None for HEAD request."""
|
||||||
|
view.request = self.req.head('/')
|
||||||
|
self.assertEqual(view.DATA, None)
|
||||||
|
|
||||||
def ensure_determines_form_content_POST(self, view):
|
def ensure_determines_form_content_POST(self, view):
|
||||||
"""Ensure view.DATA returns content for POST request with form content."""
|
"""Ensure view.DATA returns content for POST request with form content."""
|
||||||
form_data = {'qwerty': 'uiop'}
|
form_data = {'qwerty': 'uiop'}
|
||||||
|
@ -50,6 +54,10 @@ class TestContentParsing(TestCase):
|
||||||
"""Ensure view.DATA returns None for GET request with no content."""
|
"""Ensure view.DATA returns None for GET request with no content."""
|
||||||
self.ensure_determines_no_content_GET(RequestMixin())
|
self.ensure_determines_no_content_GET(RequestMixin())
|
||||||
|
|
||||||
|
def test_standard_behaviour_determines_no_content_HEAD(self):
|
||||||
|
"""Ensure view.DATA returns None for HEAD request."""
|
||||||
|
self.ensure_determines_no_content_HEAD(RequestMixin())
|
||||||
|
|
||||||
def test_standard_behaviour_determines_form_content_POST(self):
|
def test_standard_behaviour_determines_form_content_POST(self):
|
||||||
"""Ensure view.DATA returns content for POST request with form content."""
|
"""Ensure view.DATA returns content for POST request with form content."""
|
||||||
self.ensure_determines_form_content_POST(RequestMixin())
|
self.ensure_determines_form_content_POST(RequestMixin())
|
||||||
|
|
|
@ -24,3 +24,9 @@ class TestMethodOverloading(TestCase):
|
||||||
view = RequestMixin()
|
view = RequestMixin()
|
||||||
view.request = self.req.post('/', {view._METHOD_PARAM: 'DELETE'})
|
view.request = self.req.post('/', {view._METHOD_PARAM: 'DELETE'})
|
||||||
self.assertEqual(view.method, 'DELETE')
|
self.assertEqual(view.method, 'DELETE')
|
||||||
|
|
||||||
|
def test_HEAD_is_a_valid_method(self):
|
||||||
|
"""HEAD requests identified"""
|
||||||
|
view = RequestMixin()
|
||||||
|
view.request = self.req.head('/')
|
||||||
|
self.assertEqual(view.method, 'HEAD')
|
||||||
|
|
|
@ -55,6 +55,13 @@ class RendererIntegrationTests(TestCase):
|
||||||
self.assertEquals(resp.content, RENDERER_A_SERIALIZER(DUMMYCONTENT))
|
self.assertEquals(resp.content, RENDERER_A_SERIALIZER(DUMMYCONTENT))
|
||||||
self.assertEquals(resp.status_code, DUMMYSTATUS)
|
self.assertEquals(resp.status_code, DUMMYSTATUS)
|
||||||
|
|
||||||
|
def test_head_method_serializes_no_content(self):
|
||||||
|
"""No response must be included in HEAD requests."""
|
||||||
|
resp = self.client.head('/')
|
||||||
|
self.assertEquals(resp.status_code, DUMMYSTATUS)
|
||||||
|
self.assertEquals(resp['Content-Type'], RendererA.media_type)
|
||||||
|
self.assertEquals(resp.content, '')
|
||||||
|
|
||||||
def test_default_renderer_serializes_content_on_accept_any(self):
|
def test_default_renderer_serializes_content_on_accept_any(self):
|
||||||
"""If the Accept header is set to */* the default renderer should serialize the response."""
|
"""If the Accept header is set to */* the default renderer should serialize the response."""
|
||||||
resp = self.client.get('/', HTTP_ACCEPT='*/*')
|
resp = self.client.get('/', HTTP_ACCEPT='*/*')
|
||||||
|
@ -83,8 +90,6 @@ class RendererIntegrationTests(TestCase):
|
||||||
resp = self.client.get('/', HTTP_ACCEPT='foo/bar')
|
resp = self.client.get('/', HTTP_ACCEPT='foo/bar')
|
||||||
self.assertEquals(resp.status_code, 406)
|
self.assertEquals(resp.status_code, 406)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
_flat_repr = '{"foo": ["bar", "baz"]}'
|
_flat_repr = '{"foo": ["bar", "baz"]}'
|
||||||
|
|
||||||
_indented_repr = """{
|
_indented_repr = """{
|
||||||
|
|
Loading…
Reference in New Issue
Block a user