Commit d9cba639 by Tom Christie

Clean up bits of templates etc

parent f4670c89
...@@ -5,10 +5,10 @@ Django REST framework also provides HTML and PlainText renderers that help self- ...@@ -5,10 +5,10 @@ Django REST framework also provides HTML and PlainText renderers that help self-
by serializing the output along with documentation regarding the View, output status and headers, by serializing the output along with documentation regarding the View, output status and headers,
and providing forms and links depending on the allowed methods, renderers and parsers on the View. and providing forms and links depending on the allowed methods, renderers and parsers on the View.
""" """
import string
from django import forms from django import forms
from django.template import RequestContext, loader from django.template import RequestContext, loader
from django.utils import simplejson as json from django.utils import simplejson as json
from rest_framework.compat import yaml from rest_framework.compat import yaml
from rest_framework.settings import api_settings from rest_framework.settings import api_settings
from rest_framework.utils import dict2xml from rest_framework.utils import dict2xml
...@@ -16,9 +16,7 @@ from rest_framework.utils import encoders ...@@ -16,9 +16,7 @@ from rest_framework.utils import encoders
from rest_framework.utils.breadcrumbs import get_breadcrumbs from rest_framework.utils.breadcrumbs import get_breadcrumbs
from rest_framework.utils.mediatypes import get_media_type_params, add_media_type_param, media_type_matches from rest_framework.utils.mediatypes import get_media_type_params, add_media_type_param, media_type_matches
from rest_framework import VERSION from rest_framework import VERSION
from rest_framework.fields import FloatField, IntegerField, DateTimeField, DateField, EmailField, CharField, BooleanField from rest_framework import serializers
import string
class BaseRenderer(object): class BaseRenderer(object):
...@@ -27,8 +25,6 @@ class BaseRenderer(object): ...@@ -27,8 +25,6 @@ class BaseRenderer(object):
and override the :meth:`render` method. and override the :meth:`render` method.
""" """
_FORMAT_QUERY_PARAM = 'format'
media_type = None media_type = None
format = None format = None
...@@ -72,7 +68,7 @@ class BaseRenderer(object): ...@@ -72,7 +68,7 @@ class BaseRenderer(object):
class JSONRenderer(BaseRenderer): class JSONRenderer(BaseRenderer):
""" """
Renderer which serializes to JSON Renderer which serializes to json.
""" """
media_type = 'application/json' media_type = 'application/json'
...@@ -81,7 +77,7 @@ class JSONRenderer(BaseRenderer): ...@@ -81,7 +77,7 @@ class JSONRenderer(BaseRenderer):
def render(self, obj=None, media_type=None): def render(self, obj=None, media_type=None):
""" """
Renders *obj* into serialized JSON. Render `obj` into json.
""" """
if obj is None: if obj is None:
return '' return ''
...@@ -96,28 +92,37 @@ class JSONRenderer(BaseRenderer): ...@@ -96,28 +92,37 @@ class JSONRenderer(BaseRenderer):
except (ValueError, TypeError): except (ValueError, TypeError):
indent = None indent = None
return json.dumps(obj, cls=self.encoder_class, indent=indent, sort_keys=sort_keys) return json.dumps(obj, cls=self.encoder_class,
indent=indent, sort_keys=sort_keys)
class JSONPRenderer(JSONRenderer): class JSONPRenderer(JSONRenderer):
""" """
Renderer which serializes to JSONP Renderer which serializes to json,
wrapping the json output in a callback function.
""" """
media_type = 'application/javascript' media_type = 'application/javascript'
format = 'jsonp' format = 'jsonp'
renderer_class = JSONRenderer
callback_parameter = 'callback' callback_parameter = 'callback'
default_callback = 'callback'
def _get_callback(self): def get_callback(self):
return self.view.request.GET.get(self.callback_parameter, self.callback_parameter) """
Determine the name of the callback to wrap around the json output.
def _get_renderer(self): """
return self.renderer_class(self.view) params = self.view.request.GET
return params.get(self.callback_parameter, self.default_callback)
def render(self, obj=None, media_type=None): def render(self, obj=None, media_type=None):
callback = self._get_callback() """
json = self._get_renderer().render(obj, media_type) Renders into jsonp, wrapping the json output in a callback function.
Clients may set the callback function name using a query parameter
on the URL, for example: ?callback=exampleCallbackName
"""
callback = self.get_callback()
json = super(JSONPRenderer, self).render(obj, media_type)
return "%s(%s);" % (callback, json) return "%s(%s);" % (callback, json)
...@@ -180,13 +185,13 @@ class TemplateRenderer(BaseRenderer): ...@@ -180,13 +185,13 @@ class TemplateRenderer(BaseRenderer):
return template.render(context) return template.render(context)
class DocumentingTemplateRenderer(BaseRenderer): class DocumentingHTMLRenderer(BaseRenderer):
""" """
Base class for renderers used to self-document the API. HTML renderer used to self-document the API.
Implementing classes should extend this class and set the template attribute.
""" """
media_type = 'text/html'
template = None format = 'html'
template = 'rest_framework/api.html'
def _get_content(self, view, request, obj, media_type): def _get_content(self, view, request, obj, media_type):
""" """
...@@ -198,7 +203,7 @@ class DocumentingTemplateRenderer(BaseRenderer): ...@@ -198,7 +203,7 @@ class DocumentingTemplateRenderer(BaseRenderer):
# Find the first valid renderer and render the content. (Don't use another documenting renderer.) # Find the first valid renderer and render the content. (Don't use another documenting renderer.)
renderers = [renderer for renderer in view.renderer_classes renderers = [renderer for renderer in view.renderer_classes
if not issubclass(renderer, DocumentingTemplateRenderer)] if not issubclass(renderer, DocumentingHTMLRenderer)]
if not renderers: if not renderers:
return '[No renderers were found]' return '[No renderers were found]'
...@@ -219,13 +224,13 @@ class DocumentingTemplateRenderer(BaseRenderer): ...@@ -219,13 +224,13 @@ class DocumentingTemplateRenderer(BaseRenderer):
return return
# We need to map our Fields to Django's Fields. # We need to map our Fields to Django's Fields.
field_mapping = dict([ field_mapping = dict([
[FloatField.__name__, forms.FloatField], [serializers.FloatField.__name__, forms.FloatField],
[IntegerField.__name__, forms.IntegerField], [serializers.IntegerField.__name__, forms.IntegerField],
[DateTimeField.__name__, forms.DateTimeField], [serializers.DateTimeField.__name__, forms.DateTimeField],
[DateField.__name__, forms.DateField], [serializers.DateField.__name__, forms.DateField],
[EmailField.__name__, forms.EmailField], [serializers.EmailField.__name__, forms.EmailField],
[CharField.__name__, forms.CharField], [serializers.CharField.__name__, forms.CharField],
[BooleanField.__name__, forms.BooleanField] [serializers.BooleanField.__name__, forms.BooleanField]
]) ])
# Creating an on the fly form see: http://stackoverflow.com/questions/3915024/dynamically-creating-classes-python # Creating an on the fly form see: http://stackoverflow.com/questions/3915024/dynamically-creating-classes-python
...@@ -299,8 +304,11 @@ class DocumentingTemplateRenderer(BaseRenderer): ...@@ -299,8 +304,11 @@ class DocumentingTemplateRenderer(BaseRenderer):
The context used in the template contains all the information The context used in the template contains all the information
needed to self-document the response to this request. needed to self-document the response to this request.
""" """
view = self.view
request = view.request
response = view.response
content = self._get_content(self.view, self.view.request, obj, media_type) content = self._get_content(view, request, obj, media_type)
put_form_instance = self._get_form_instance(self.view, 'put') put_form_instance = self._get_form_instance(self.view, 'put')
post_form_instance = self._get_form_instance(self.view, 'post') post_form_instance = self._get_form_instance(self.view, 'post')
...@@ -313,9 +321,9 @@ class DocumentingTemplateRenderer(BaseRenderer): ...@@ -313,9 +321,9 @@ class DocumentingTemplateRenderer(BaseRenderer):
template = loader.get_template(self.template) template = loader.get_template(self.template)
context = RequestContext(self.view.request, { context = RequestContext(self.view.request, {
'content': content, 'content': content,
'view': self.view, 'view': view,
'request': self.view.request, 'request': request,
'response': self.view.response, 'response': response,
'description': description, 'description': description,
'name': name, 'name': name,
'version': VERSION, 'version': VERSION,
...@@ -324,8 +332,6 @@ class DocumentingTemplateRenderer(BaseRenderer): ...@@ -324,8 +332,6 @@ class DocumentingTemplateRenderer(BaseRenderer):
'available_formats': [renderer.format for renderer in self.view.renderer_classes], 'available_formats': [renderer.format for renderer in self.view.renderer_classes],
'put_form': put_form_instance, 'put_form': put_form_instance,
'post_form': post_form_instance, 'post_form': post_form_instance,
'FORMAT_PARAM': self._FORMAT_QUERY_PARAM,
'METHOD_PARAM': getattr(self.view, '_METHOD_PARAM', None),
'api_settings': api_settings 'api_settings': api_settings
}) })
...@@ -338,53 +344,3 @@ class DocumentingTemplateRenderer(BaseRenderer): ...@@ -338,53 +344,3 @@ class DocumentingTemplateRenderer(BaseRenderer):
self.view.response.status_code = 200 self.view.response.status_code = 200
return ret return ret
class DocumentingHTMLRenderer(DocumentingTemplateRenderer):
"""
Renderer which provides a browsable HTML interface for an API.
See the examples at http://api.django-rest-framework.org to see this in action.
"""
media_type = 'text/html'
format = 'html'
template = 'rest_framework/api.html'
class DocumentingXHTMLRenderer(DocumentingTemplateRenderer):
"""
Identical to DocumentingHTMLRenderer, except with an xhtml media type.
We need this to be listed in preference to xml in order to return HTML to WebKit based browsers,
given their Accept headers.
"""
media_type = 'application/xhtml+xml'
format = 'xhtml'
template = 'rest_framework/api.html'
class DocumentingPlainTextRenderer(DocumentingTemplateRenderer):
"""
Renderer that serializes the object with the default renderer, but also provides plain-text
documentation of the returned status and headers, and of the resource's name and description.
Useful for browsing an API with command line tools.
"""
media_type = 'text/plain'
format = 'txt'
template = 'rest_framework/api.txt'
DEFAULT_RENDERERS = (
JSONRenderer,
JSONPRenderer,
DocumentingHTMLRenderer,
DocumentingXHTMLRenderer,
DocumentingPlainTextRenderer,
XMLRenderer
)
if yaml:
DEFAULT_RENDERERS += (YAMLRenderer, )
else:
YAMLRenderer = None
from django.template.response import SimpleTemplateResponse
from django.core.handlers.wsgi import STATUS_CODE_TEXT from django.core.handlers.wsgi import STATUS_CODE_TEXT
from django.template.response import SimpleTemplateResponse
class Response(SimpleTemplateResponse): class Response(SimpleTemplateResponse):
......
from decimal import Decimal
from django.core.serializers.base import DeserializedObject
from django.utils.datastructures import SortedDict
import copy import copy
import datetime import datetime
import types import types
from decimal import Decimal
from django.core.serializers.base import DeserializedObject
from django.utils.datastructures import SortedDict
from rest_framework.fields import * from rest_framework.fields import *
......
...@@ -24,9 +24,7 @@ from django.utils import importlib ...@@ -24,9 +24,7 @@ from django.utils import importlib
DEFAULTS = { DEFAULTS = {
'DEFAULT_RENDERERS': ( 'DEFAULT_RENDERERS': (
'rest_framework.renderers.JSONRenderer', 'rest_framework.renderers.JSONRenderer',
'rest_framework.renderers.JSONPRenderer',
'rest_framework.renderers.DocumentingHTMLRenderer', 'rest_framework.renderers.DocumentingHTMLRenderer',
'rest_framework.renderers.DocumentingPlainTextRenderer',
), ),
'DEFAULT_PARSERS': ( 'DEFAULT_PARSERS': (
'rest_framework.parsers.JSONParser', 'rest_framework.parsers.JSONParser',
...@@ -38,7 +36,8 @@ DEFAULTS = { ...@@ -38,7 +36,8 @@ DEFAULTS = {
), ),
'DEFAULT_PERMISSIONS': (), 'DEFAULT_PERMISSIONS': (),
'DEFAULT_THROTTLES': (), 'DEFAULT_THROTTLES': (),
'DEFAULT_CONTENT_NEGOTIATION': 'rest_framework.negotiation.DefaultContentNegotiation', 'DEFAULT_CONTENT_NEGOTIATION':
'rest_framework.negotiation.DefaultContentNegotiation',
'UNAUTHENTICATED_USER': 'django.contrib.auth.models.AnonymousUser', 'UNAUTHENTICATED_USER': 'django.contrib.auth.models.AnonymousUser',
'UNAUTHENTICATED_TOKEN': None, 'UNAUTHENTICATED_TOKEN': None,
......
prettyPrint();
$('.js-tooltip').tooltip({
delay: 1000
});
{% autoescape off %}{{ name }}
{{ description }}
HTTP {{ response.status_code }} {{ response.status_text }}
{% for key, val in response.headers.items %}{{ key }}: {{ val }}
{% endfor %}
{{ content }}{% endautoescape %}
...@@ -4,26 +4,28 @@ ...@@ -4,26 +4,28 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
{% block head %}
{% block meta %}
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<meta name="robots" content="NONE,NOARCHIVE" />
{% endblock %}
<title>{% block title %}Django REST framework{% endblock %}</title>
{% block bootstrap_theme %} {% block style %}
<link rel="stylesheet" type="text/css" href="{% get_static_prefix %}rest_framework/css/bootstrap.min.css"/> <link rel="stylesheet" type="text/css" href="{% get_static_prefix %}rest_framework/css/bootstrap.min.css"/>
<link rel="stylesheet" type="text/css" href="{% get_static_prefix %}rest_framework/css/bootstrap-tweaks.css"/> <link rel="stylesheet" type="text/css" href="{% get_static_prefix %}rest_framework/css/bootstrap-tweaks.css"/>
{% endblock %}
<link rel="stylesheet" type="text/css" href='{% get_static_prefix %}rest_framework/css/prettify.css'/> <link rel="stylesheet" type="text/css" href='{% get_static_prefix %}rest_framework/css/prettify.css'/>
<link rel="stylesheet" type="text/css" href='{% get_static_prefix %}rest_framework/css/style.css'/> <link rel="stylesheet" type="text/css" href='{% get_static_prefix %}rest_framework/css/default.css'/>
{% block extrastyle %}{% endblock %} {% endblock %}
<title>{% block title %}Django REST framework - {{ name }}{% endblock %}</title>
{% block extrahead %}{% endblock %}
{% block blockbots %}<meta name="robots" content="NONE,NOARCHIVE" />{% endblock %}
{% endblock %}
</head> </head>
<body class="{% block bodyclass %}{% endblock %} container"> <body class="{% block bodyclass %}{% endblock %} container">
{% block navbar %}
<div class="navbar navbar-fixed-top {% block bootstrap_navbar_variant %}navbar-inverse{% endblock %}"> <div class="navbar navbar-fixed-top {% block bootstrap_navbar_variant %}navbar-inverse{% endblock %}">
<div class="navbar-inner"> <div class="navbar-inner">
<div class="container"> <div class="container">
...@@ -32,31 +34,28 @@ ...@@ -32,31 +34,28 @@
</span> </span>
<ul class="nav pull-right"> <ul class="nav pull-right">
{% block userlinks %} {% block userlinks %}
{% if user.is_active %} {% if user.is_authenticated %}
<li class="dropdown"> <li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown"> <a href="#" class="dropdown-toggle" data-toggle="dropdown">
Welcome, {{ user }} Welcome, {{ user }}
<b class="caret"></b> <b class="caret"></b>
</a> </a>
<ul class="dropdown-menu"> <ul class="dropdown-menu">
<li>{% optional_logout %}</li> <li>{% optional_logout request %}</li>
</ul> </ul>
</li> </li>
{% else %} {% else %}
<li>{% optional_login %}</li> <li>{% optional_login request %}</li>
{% endif %} {% endif %}
{% endblock %} {% endblock %}
</ul> </ul>
</div> </div>
</div> </div>
</div> </div>
{% endblock %}
{% block global_heading %}{% endblock %}
{% block breadcrumbs %} {% block breadcrumbs %}
<ul class="breadcrumb"> <ul class="breadcrumb">
{% for breadcrumb_name, breadcrumb_url in breadcrumblist %} {% for breadcrumb_name, breadcrumb_url in breadcrumblist %}
<li> <li>
<a href="{{ breadcrumb_url }}" {% if forloop.last %}class="active"{% endif %}>{{ breadcrumb_name }}</a> {% if not forloop.last %}<span class="divider">&rsaquo;</span>{% endif %} <a href="{{ breadcrumb_url }}" {% if forloop.last %}class="active"{% endif %}>{{ breadcrumb_name }}</a> {% if not forloop.last %}<span class="divider">&rsaquo;</span>{% endif %}
...@@ -79,11 +78,9 @@ ...@@ -79,11 +78,9 @@
</button> </button>
<ul class="dropdown-menu"> <ul class="dropdown-menu">
{% for format in available_formats %} {% for format in available_formats %}
{% with FORMAT_PARAM|add:"="|add:format as param %}
<li> <li>
<a class="js-tooltip format-option" href='{{ request.get_full_path|add_query_param:param }}' rel="nofollow" title="Do a GET request on the {{ name }} resource with the format set to `{{ format }}`">{{ format }}</a> <a class="js-tooltip format-option" href='{% add_query_param request api_settings.URL_FORMAT_OVERRIDE format %}' rel="nofollow" title="Do a GET request on the {{ name }} resource with the format set to `{{ format }}`">{{ format }}</a>
</li> </li>
{% endwith %}
{% endfor %} {% endfor %}
</ul> </ul>
</div> </div>
...@@ -188,24 +185,19 @@ ...@@ -188,24 +185,19 @@
</div> </div>
<!-- END Content --> <!-- END Content -->
<div id="footer">
{% block footer %} {% block footer %}
<div id="footer">
<a class="powered-by" href='http://django-rest-framework.org'>Django REST framework</a> <span class="version">{{ version }}</span> <a class="powered-by" href='http://django-rest-framework.org'>Django REST framework</a> <span class="version">{{ version }}</span>
{% endblock %}
</div> </div>
{% endblock %}
</div> </div>
{% block script %}
<script src="{% get_static_prefix %}rest_framework/js/jquery-1.8.1-min.js"></script> <script src="{% get_static_prefix %}rest_framework/js/jquery-1.8.1-min.js"></script>
<script src="{% get_static_prefix %}rest_framework/js/bootstrap.min.js"></script> <script src="{% get_static_prefix %}rest_framework/js/bootstrap.min.js"></script>
<script src="{% get_static_prefix %}rest_framework/js/prettify-min.js"></script> <script src="{% get_static_prefix %}rest_framework/js/prettify-min.js"></script>
<script> <script src="{% get_static_prefix %}rest_framework/js/default.js"></script>
prettyPrint(); {% endblock %}
$('.js-tooltip').tooltip({
delay: 1000
});
</script>
{% block extrabody %}{% endblock %}
</body> </body>
</html> </html>
...@@ -46,8 +46,8 @@ def replace_query_param(url, key, val): ...@@ -46,8 +46,8 @@ def replace_query_param(url, key, val):
# And the template tags themselves... # And the template tags themselves...
@register.simple_tag(takes_context=True) @register.simple_tag
def optional_login(context): def optional_login(request):
""" """
Include a login snippet if REST framework's login view is in the URLconf. Include a login snippet if REST framework's login view is in the URLconf.
""" """
...@@ -56,13 +56,12 @@ def optional_login(context): ...@@ -56,13 +56,12 @@ def optional_login(context):
except NoReverseMatch: except NoReverseMatch:
return '' return ''
request = context['request']
snippet = "<a href='%s?next=%s'>Log in</a>" % (login_url, request.path) snippet = "<a href='%s?next=%s'>Log in</a>" % (login_url, request.path)
return snippet return snippet
@register.simple_tag(takes_context=True) @register.simple_tag
def optional_logout(context): def optional_logout(request):
""" """
Include a logout snippet if REST framework's logout view is in the URLconf. Include a logout snippet if REST framework's logout view is in the URLconf.
""" """
...@@ -71,17 +70,16 @@ def optional_logout(context): ...@@ -71,17 +70,16 @@ def optional_logout(context):
except NoReverseMatch: except NoReverseMatch:
return '' return ''
request = context['request']
snippet = "<a href='%s?next=%s'>Log out</a>" % (logout_url, request.path) snippet = "<a href='%s?next=%s'>Log out</a>" % (logout_url, request.path)
return snippet return snippet
@register.filter @register.simple_tag
def add_query_param(url, param): def add_query_param(request, key, val):
""" """
Add a query parameter to the current request url, and return the new url.
""" """
key, val = param.split('=') return replace_query_param(request.get_full_path(), key, val)
return replace_query_param(url, key, val)
@register.filter @register.filter
...@@ -114,7 +112,7 @@ def add_class(value, css_class): ...@@ -114,7 +112,7 @@ def add_class(value, css_class):
return value return value
@register.filter(is_safe=True) @register.filter
def urlize_quoted_links(text, trim_url_limit=None, nofollow=True, autoescape=True): def urlize_quoted_links(text, trim_url_limit=None, nofollow=True, autoescape=True):
""" """
Converts any URLs in text into clickable links. Converts any URLs in text into clickable links.
...@@ -170,4 +168,4 @@ def urlize_quoted_links(text, trim_url_limit=None, nofollow=True, autoescape=Tru ...@@ -170,4 +168,4 @@ def urlize_quoted_links(text, trim_url_limit=None, nofollow=True, autoescape=Tru
words[i] = mark_safe(word) words[i] = mark_safe(word)
elif autoescape: elif autoescape:
words[i] = escape(word) words[i] = escape(word)
return u''.join(words) return mark_safe(u''.join(words))
...@@ -4,6 +4,7 @@ from django.conf.urls.defaults import patterns, url, include ...@@ -4,6 +4,7 @@ from django.conf.urls.defaults import patterns, url, include
from django.test import TestCase from django.test import TestCase
from rest_framework import status from rest_framework import status
from rest_framework.compat import yaml
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework.views import APIView from rest_framework.views import APIView
from rest_framework.renderers import BaseRenderer, JSONRenderer, YAMLRenderer, \ from rest_framework.renderers import BaseRenderer, JSONRenderer, YAMLRenderer, \
...@@ -246,7 +247,7 @@ class JSONPRendererTests(TestCase): ...@@ -246,7 +247,7 @@ class JSONPRendererTests(TestCase):
self.assertEquals(resp.content, '%s(%s);' % (callback_func, _flat_repr)) self.assertEquals(resp.content, '%s(%s);' % (callback_func, _flat_repr))
if YAMLRenderer: if yaml:
_yaml_repr = 'foo: [bar, baz]\n' _yaml_repr = 'foo: [bar, baz]\n'
class YAMLRendererTests(TestCase): class YAMLRendererTests(TestCase):
......
import time
from django.core.cache import cache from django.core.cache import cache
from rest_framework.settings import api_settings from rest_framework.settings import api_settings
import time
class BaseThrottle(object): class BaseThrottle(object):
......
...@@ -11,12 +11,11 @@ from django.http import Http404 ...@@ -11,12 +11,11 @@ from django.http import Http404
from django.utils.html import escape from django.utils.html import escape
from django.utils.safestring import mark_safe from django.utils.safestring import mark_safe
from django.views.decorators.csrf import csrf_exempt from django.views.decorators.csrf import csrf_exempt
from rest_framework import status, exceptions
from rest_framework.compat import View as _View, apply_markdown from rest_framework.compat import View, apply_markdown
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework.request import Request from rest_framework.request import Request
from rest_framework.settings import api_settings from rest_framework.settings import api_settings
from rest_framework import status, exceptions
def _remove_trailing_string(content, trailing): def _remove_trailing_string(content, trailing):
...@@ -53,7 +52,7 @@ def _camelcase_to_spaces(content): ...@@ -53,7 +52,7 @@ def _camelcase_to_spaces(content):
return re.sub(camelcase_boundry, ' \\1', content).strip() return re.sub(camelcase_boundry, ' \\1', content).strip()
class APIView(_View): class APIView(View):
settings = api_settings settings = api_settings
renderer_classes = api_settings.DEFAULT_RENDERERS renderer_classes = api_settings.DEFAULT_RENDERERS
...@@ -86,7 +85,7 @@ class APIView(_View): ...@@ -86,7 +85,7 @@ class APIView(_View):
def default_response_headers(self): def default_response_headers(self):
return { return {
'Allow': ', '.join(self.allowed_methods), 'Allow': ', '.join(self.allowed_methods),
'Vary': 'Authenticate, Accept' 'Vary': 'Accept'
} }
def get_name(self): def get_name(self):
......
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