Merging master into develop

This commit is contained in:
Tom Christie 2012-02-21 20:12:14 +00:00
parent 21fcd3a906
commit af9e4f69d7
29 changed files with 244 additions and 107 deletions

View File

@ -31,6 +31,8 @@ Ben Timby <btimby>
Michele Lazzeri <michelelazzeri-nextage>
Camille Harang <mammique>
Paul Oswald <poswald>
Sean C. Farley <scfarley>
Daniel Izquierdo <izquierdo>
THANKS TO:

View File

@ -1,16 +1,19 @@
Release Notes
=============
development
-----------
0.3.3
-----
* Added DjangoModelPermissions class to support `django.contrib.auth` style permissions.
* Use `staticfiles` for css files.
- Easier to override. Won't conflict with customised admin styles (eg grappelli)
* Templates are now nicely namespaced.
- Allows easier overriding.
* Drop implied 'pk' filter if last arg in urlconf is unnamed.
- Too magical. Explict is better than implicit.
* Saner template variable autoescaping.
* Tider setup.py
* Updated for URLObject 2.0
* Bugfixes:
- Bug with PerUserThrottling when user contains unicode chars.

View File

@ -1,3 +1,3 @@
__version__ = '0.3.3-dev'
__version__ = '0.3.3'
VERSION = __version__ # synonym

View File

@ -497,12 +497,12 @@ class PaginatorMixin(object):
"""
Constructs a url used for getting the next/previous urls
"""
url = URLObject.parse(self.request.get_full_path())
url = url.set_query_param('page', page_number)
url = URLObject(self.request.get_full_path())
url = url.set_query_param('page', str(page_number))
limit = self.get_limit()
if limit != self.limit:
url = url.add_query_param('limit', limit)
url = url.set_query_param('limit', str(limit))
return url

View File

@ -379,7 +379,7 @@ class DocumentingHTMLRenderer(DocumentingTemplateRenderer):
media_type = 'text/html'
format = 'html'
template = 'renderer.html'
template = 'djangorestframework/api.html'
class DocumentingXHTMLRenderer(DocumentingTemplateRenderer):
@ -391,7 +391,7 @@ class DocumentingXHTMLRenderer(DocumentingTemplateRenderer):
media_type = 'application/xhtml+xml'
format = 'xhtml'
template = 'renderer.html'
template = 'djangorestframework/api.html'
class DocumentingPlainTextRenderer(DocumentingTemplateRenderer):
@ -403,7 +403,7 @@ class DocumentingPlainTextRenderer(DocumentingTemplateRenderer):
media_type = 'text/plain'
format = 'txt'
template = 'renderer.txt'
template = 'djangorestframework/api.txt'
DEFAULT_RENDERERS = (

View File

@ -1,10 +1,10 @@
from django import forms
from django.core.urlresolvers import reverse, get_urlconf, get_resolver, NoReverseMatch
from django.core.urlresolvers import get_urlconf, get_resolver, NoReverseMatch
from django.db import models
from djangorestframework.response import ImmediateResponse
from djangorestframework.serializer import Serializer, _SkipField
from djangorestframework.utils import as_tuple
from djangorestframework.utils import as_tuple, reverse
class BaseResource(Serializer):
@ -354,7 +354,7 @@ class ModelResource(FormResource):
instance_attrs[param] = attr
try:
return reverse(self.view_callable[0], kwargs=instance_attrs)
return reverse(self.view_callable[0], self.view.request, kwargs=instance_attrs)
except NoReverseMatch:
pass
raise _SkipField

View File

@ -40,7 +40,7 @@ class Response(SimpleTemplateResponse):
_ACCEPT_QUERY_PARAM = '_accept' # Allow override of Accept header in URL query params
_IGNORE_IE_ACCEPT_HEADER = True
def __init__(self, content=None, status=None, request=None, renderers=None):
def __init__(self, content=None, status=None, request=None, renderers=None, headers=None):
# First argument taken by `SimpleTemplateResponse.__init__` is template_name,
# which we don't need
super(Response, self).__init__(None, status=status)
@ -50,6 +50,7 @@ class Response(SimpleTemplateResponse):
self.raw_content = content
self.has_content_body = content is not None
self.request = request
self.headers = headers and headers[:] or []
if renderers is not None:
self.renderers = renderers

View File

@ -146,7 +146,7 @@ class Serializer(object):
# then the second element of the tuple is the fields to
# set on the related serializer
if isinstance(info, (list, tuple)):
class OnTheFlySerializer(Serializer):
class OnTheFlySerializer(self.__class__):
fields = info
return OnTheFlySerializer

View File

@ -0,0 +1,3 @@
{% extends "djangorestframework/base.html" %}
{# Override this template in your own templates directory to customize #}

View File

@ -7,26 +7,34 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<link rel="stylesheet" type="text/css" href='{% get_static_prefix %}djangorestframework/css/style.css'/>
<title>Django REST framework - {{ name }}</title>
{% block extrastyle %}{% endblock %}
<title>{% block title %}Django REST framework - {{ name }}{% endblock %}</title>
{% block extrahead %}{% endblock %}
{% block blockbots %}<meta name="robots" content="NONE,NOARCHIVE" />{% endblock %}
</head>
<body>
<body class="{% block bodyclass %}{% endblock %}">
<div id="container">
<div id="header">
<div id="branding">
<h1 id="site-name"><a href='http://django-rest-framework.org'>Django REST framework</a> <span class="version"> v {{ version }}</span></h1>
<h1 id="site-name">{% block branding %}<a href='http://django-rest-framework.org'>Django REST framework</a> <span class="version"> v {{ version }}</span>{% endblock %}</h1>
</div>
<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 %}
{% block userlinks %}{% endblock %}
</div>
{% block nav-global %}{% endblock %}
</div>
<div class="breadcrumbs">
{% block breadcrumbs %}
{% for breadcrumb_name, breadcrumb_url in breadcrumblist %}
<a href="{{ breadcrumb_url }}">{{ breadcrumb_name }}</a> {% if not forloop.last %}&rsaquo;{% endif %}
{% endfor %}
{% endblock %}
</div>
<!-- Content -->
<div id="content" class="{% block coltype %}colM{% endblock %}">
{% if 'OPTIONS' in allowed_methods %}
@ -123,7 +131,12 @@
{% endif %}
</div>
<!-- END content-main -->
</div>
<!-- END Content -->
{% block footer %}<div id="footer"></div>{% endblock %}
</div>
</body>
</html>

View File

@ -4,8 +4,7 @@ register = Library()
def add_query_param(url, param):
(key, sep, val) = param.partition('=')
return unicode(URLObject.parse(url) & (key, val))
return unicode(URLObject(url).with_query(param))
register.filter('add_query_param', add_query_param)

View File

@ -1,8 +1,8 @@
from django.conf.urls.defaults import patterns, url
from django.core.urlresolvers import reverse
from django.test import TestCase
from django.utils import simplejson as json
from djangorestframework.utils import reverse
from djangorestframework.views import View
from djangorestframework.response import Response
@ -12,7 +12,7 @@ class MockView(View):
permissions = ()
def get(self, request):
return Response(reverse('another'))
return Response(reverse('another', request))
urlpatterns = patterns('',
url(r'^$', MockView.as_view()),

View File

@ -1,6 +1,7 @@
import django
from django.utils.encoding import smart_unicode
from django.utils.xmlutils import SimplerXMLGenerator
from django.core.urlresolvers import resolve
from django.core.urlresolvers import resolve, reverse as django_reverse
from django.conf import settings
from djangorestframework.compat import StringIO
@ -180,3 +181,21 @@ class XMLRenderer():
def dict2xml(input):
return XMLRenderer().dict2xml(input)
def reverse(viewname, request, *args, **kwargs):
"""
Do the same as :py:func:`django.core.urlresolvers.reverse` but using
*request* to build a fully qualified URL.
"""
return request.build_absolute_uri(django_reverse(viewname, *args, **kwargs))
if django.VERSION >= (1, 4):
from django.core.urlresolvers import reverse_lazy as django_reverse_lazy
def reverse_lazy(viewname, request, *args, **kwargs):
"""
Do the same as :py:func:`django.core.urlresolvers.reverse_lazy` but using
*request* to build a fully qualified URL.
"""
return request.build_absolute_uri(django_reverse_lazy(viewname, *args, **kwargs))

View File

@ -12,7 +12,7 @@ import base64
# be making settings changes in order to accomodate django-rest-framework
@csrf_protect
@never_cache
def api_login(request, template_name='api_login.html',
def api_login(request, template_name='djangorestframework/login.html',
redirect_field_name=REDIRECT_FIELD_NAME,
authentication_form=AuthenticationForm):
"""Displays the login form and handles the login action."""
@ -57,5 +57,5 @@ def api_login(request, template_name='api_login.html',
}, context_instance=RequestContext(request))
def api_logout(request, next_page=None, template_name='api_login.html', redirect_field_name=REDIRECT_FIELD_NAME):
def api_logout(request, next_page=None, template_name='djangorestframework/login.html', redirect_field_name=REDIRECT_FIELD_NAME):
return logout(request, next_page, template_name, redirect_field_name)

View File

@ -188,22 +188,13 @@ class View(ResourceMixin, RequestMixin, ResponseMixin, AuthMixin, DjangoView):
Required if you want to do things like set `request.upload_handlers` before
the authentication and dispatch handling is run.
"""
# Calls to 'reverse' will not be fully qualified unless we set the
# scheme/host/port here.
self.orig_prefix = get_script_prefix()
if not (self.orig_prefix.startswith('http:') or self.orig_prefix.startswith('https:')):
prefix = '%s://%s' % (request.is_secure() and 'https' or 'http', request.get_host())
set_script_prefix(prefix + self.orig_prefix)
return request
pass
def final(self, request, response, *args, **kargs):
"""
Returns an `HttpResponse`. This method is a hook for any code that needs to run
after everything else in the view.
"""
# Restore script_prefix.
set_script_prefix(self.orig_prefix)
# Always add these headers.
response['Allow'] = ', '.join(allowed_methods(self))
# sample to allow caching using Vary http header

47
docs/howto/reverse.rst Normal file
View File

@ -0,0 +1,47 @@
Returning URIs from your Web APIs
=================================
"The central feature that distinguishes the REST architectural style from
other network-based styles is its emphasis on a uniform interface between
components."
-- Roy Fielding, Architectural Styles and the Design of Network-based Software Architectures
As a rule, it's probably better practice to return absolute URIs from you web APIs, e.g. "http://example.com/foobar", rather than returning relative URIs, e.g. "/foobar".
The advantages of doing so are:
* It's more explicit.
* It leaves less work for your API clients.
* There's no ambiguity about the meaning of the string when it's found in representations such as JSON that do not have a native URI type.
* It allows us to easily do things like markup HTML representations with hyperlinks.
Django REST framework provides two utility functions to make it simpler to return absolute URIs from your Web API.
There's no requirement for you to use them, but if you do then the self-describing API will be able to automatically hyperlink its output for you, which makes browsing the API much easier.
reverse(viewname, request, ...)
-------------------------------
The :py:func:`~utils.reverse` function has the same behavior as :py:func:`django.core.urlresolvers.reverse` [1]_, except that it takes a request object and returns a fully qualified URL, using the request to determine the host and port::
from djangorestframework.utils import reverse
from djangorestframework.views import View
class MyView(View):
def get(self, request):
context = {
'url': reverse('year-summary', request, args=[1945])
}
return Response(context)
reverse_lazy(viewname, request, ...)
------------------------------------
The :py:func:`~utils.reverse_lazy` function has the same behavior as :py:func:`django.core.urlresolvers.reverse_lazy` [2]_, except that it takes a request object and returns a fully qualified URL, using the request to determine the host and port.
.. rubric:: Footnotes
.. [1] https://docs.djangoproject.com/en/dev/topics/http/urls/#reverse
.. [2] https://docs.djangoproject.com/en/dev/topics/http/urls/#reverse-lazy

View File

@ -3,45 +3,58 @@
Setup
=====
Installing into site-packages
-----------------------------
Templates
---------
If you need to manually install Django REST framework to your ``site-packages`` directory, run the ``setup.py`` script::
Django REST framework uses a few templates for the HTML and plain text
documenting renderers. You'll need to ensure ``TEMPLATE_LOADERS`` setting
contains ``'django.template.loaders.app_directories.Loader'``.
This will already be the case by default.
python setup.py install
You may customize the templates by creating a new template called
``djangorestframework/api.html`` in your project, which should extend
``djangorestframework/base.html`` and override the appropriate
block tags. For example::
Template Loaders
----------------
{% extends "djangorestframework/base.html" %}
Django REST framework uses a few templates for the HTML and plain text documenting renderers.
{% block title %}My API{% endblock %}
* Ensure ``TEMPLATE_LOADERS`` setting contains ``'django.template.loaders.app_directories.Loader'``.
{% block branding %}
<h1 id="site-name">My API</h1>
{% endblock %}
This will be the case by default so you shouldn't normally need to do anything here.
Admin Styling
-------------
Styling
-------
Django REST framework uses the admin media for styling. When running using Django's testserver this is automatically served for you,
but once you move onto a production server, you'll want to make sure you serve the admin media separately, exactly as you would do
`if using the Django admin <https://docs.djangoproject.com/en/dev/howto/deployment/modpython/#serving-the-admin-files>`_.
Django REST framework requires `django.contrib.staticfiles`_ to serve it's css.
If you're using Django 1.2 you'll need to use the seperate
`django-staticfiles`_ package instead.
You can override the styling by creating a file in your top-level static
directory named ``djangorestframework/css/style.css``
* Ensure that the ``ADMIN_MEDIA_PREFIX`` is set appropriately and that you are serving the admin media.
(Django's testserver will automatically serve the admin media for you)
Markdown
--------
The Python `markdown library <http://www.freewisdom.org/projects/python-markdown/>`_ is not required but comes recommended.
`Python markdown`_ is not required but comes recommended.
If markdown is installed your :class:`.Resource` descriptions can include `markdown style formatting
<http://daringfireball.net/projects/markdown/syntax>`_ which will be rendered by the HTML documenting renderer.
If markdown is installed your :class:`.Resource` descriptions can include
`markdown formatting`_ which will be rendered by the self-documenting API.
login/logout
---------------------------------
YAML
----
Django REST framework comes with a few views that can be useful including an api
login and logout views::
YAML support is optional, and requires `PyYAML`_.
Login / Logout
--------------
Django REST framework includes login and logout views that are useful if
you're using the self-documenting API::
from django.conf.urls.defaults import patterns
@ -51,3 +64,9 @@ login and logout views::
(r'^accounts/logout/$', 'api_logout'),
)
.. _django.contrib.staticfiles: https://docs.djangoproject.com/en/dev/ref/contrib/staticfiles/
.. _django-staticfiles: http://pypi.python.org/pypi/django-staticfiles/
.. _URLObject: http://pypi.python.org/pypi/URLObject/
.. _Python markdown: http://www.freewisdom.org/projects/python-markdown/
.. _markdown formatting: http://daringfireball.net/projects/markdown/syntax
.. _PyYAML: http://pypi.python.org/pypi/PyYAML

View File

@ -40,8 +40,11 @@ Requirements
------------
* Python (2.5, 2.6, 2.7 supported)
* Django (1.2, 1.3, 1.4-alpha supported)
* Django (1.2, 1.3, 1.4 supported)
* `django.contrib.staticfiles`_ (or `django-staticfiles`_ for Django 1.2)
* `URLObject`_ >= 2.0.0
* `Markdown`_ >= 2.1.0 (Optional)
* `PyYAML`_ >= 3.10 (Optional)
Installation
------------
@ -54,8 +57,6 @@ Or get the latest development version using git::
git clone git@github.com:tomchristie/django-rest-framework.git
Or you can `download the current release <http://pypi.python.org/pypi/djangorestframework>`_.
Setup
-----
@ -114,3 +115,8 @@ Indices and tables
* :ref:`modindex`
* :ref:`search`
.. _django.contrib.staticfiles: https://docs.djangoproject.com/en/dev/ref/contrib/staticfiles/
.. _django-staticfiles: http://pypi.python.org/pypi/django-staticfiles/
.. _URLObject: http://pypi.python.org/pypi/URLObject/
.. _Markdown: http://pypi.python.org/pypi/Markdown/
.. _PyYAML: http://pypi.python.org/pypi/PyYAML

5
docs/library/utils.rst Normal file
View File

@ -0,0 +1,5 @@
:mod:`utils`
==============
.. automodule:: utils
:members:

View File

@ -1,5 +1,5 @@
from django.core.urlresolvers import reverse
from djangorestframework.resources import ModelResource
from djangorestframework.utils import reverse
from blogpost.models import BlogPost, Comment
@ -12,7 +12,7 @@ class BlogPostResource(ModelResource):
ordering = ('-created',)
def comments(self, instance):
return reverse('comments', kwargs={'blogpost': instance.key})
return reverse('comments', request, kwargs={'blogpost': instance.key})
class CommentResource(ModelResource):
@ -24,4 +24,4 @@ class CommentResource(ModelResource):
ordering = ('-created',)
def blogpost(self, instance):
return reverse('blog-post', kwargs={'key': instance.blogpost.key})
return reverse('blog-post', request, kwargs={'key': instance.blogpost.key})

View File

@ -1,12 +1,11 @@
"""Test a range of REST API usage of the example application.
"""
from django.core.urlresolvers import reverse
from django.test import TestCase
from django.core.urlresolvers import reverse
from django.utils import simplejson as json
from djangorestframework.compat import RequestFactory
from djangorestframework.utils import reverse
from djangorestframework.views import InstanceModelView, ListOrCreateModelView
from blogpost import models, urls

View File

@ -2,9 +2,9 @@ from djangorestframework.compat import View # Use Django 1.3's django.views.gen
from djangorestframework.mixins import ResponseMixin
from djangorestframework.renderers import DEFAULT_RENDERERS
from djangorestframework.response import Response
from djangorestframework.utils import reverse
from django.conf.urls.defaults import patterns, url
from django.core.urlresolvers import reverse
class ExampleView(ResponseMixin, View):
@ -14,7 +14,7 @@ class ExampleView(ResponseMixin, View):
def get(self, request):
response = Response({'description': 'Some example content',
'url': reverse('mixin-view')}, status=200)
'url': reverse('mixin-view', request)}, status=200)
self.response = self.prepare_response(response)
return self.response

View File

@ -1,6 +1,6 @@
from django.conf import settings
from django.core.urlresolvers import reverse
from djangorestframework.utils import reverse
from djangorestframework.views import View
from djangorestframework.response import Response
from djangorestframework import status
@ -41,7 +41,7 @@ class ObjectStoreRoot(View):
filepaths = [os.path.join(OBJECT_STORE_DIR, file) for file in os.listdir(OBJECT_STORE_DIR) if not file.startswith('.')]
ctime_sorted_basenames = [item[0] for item in sorted([(os.path.basename(path), os.path.getctime(path)) for path in filepaths],
key=operator.itemgetter(1), reverse=True)]
return Response([reverse('stored-object', kwargs={'key':key}) for key in ctime_sorted_basenames])
return Response([reverse('stored-object', request, kwargs={'key':key}) for key in ctime_sorted_basenames])
def post(self, request):
"""
@ -51,8 +51,8 @@ class ObjectStoreRoot(View):
pathname = os.path.join(OBJECT_STORE_DIR, key)
pickle.dump(self.CONTENT, open(pathname, 'wb'))
remove_oldest_files(OBJECT_STORE_DIR, MAX_FILES)
self.headers['Location'] = reverse('stored-object', kwargs={'key':key})
return Response(self.CONTENT, status=status.HTTP_201_CREATED)
url = reverse('stored-object', request, kwargs={'key':key})
return Response(self.CONTENT, status.HTTP_201_CREATED, {'Location': url})
class StoredObject(View):

View File

@ -1,7 +1,7 @@
from djangorestframework.views import View
from djangorestframework.response import Response
from djangorestframework.permissions import PerUserThrottling, IsAuthenticated
from django.core.urlresolvers import reverse
from djangorestframework.utils import reverse
class PermissionsExampleView(View):
@ -13,11 +13,11 @@ class PermissionsExampleView(View):
return Response([
{
'name': 'Throttling Example',
'url': reverse('throttled-resource')
'url': reverse('throttled-resource', request)
},
{
'name': 'Logged in example',
'url': reverse('loggedin-resource')
'url': reverse('loggedin-resource', request)
},
])

View File

@ -1,10 +1,10 @@
from __future__ import with_statement # for python 2.5
from django.conf import settings
from django.core.urlresolvers import reverse
from djangorestframework.resources import FormResource
from djangorestframework.response import Response
from djangorestframework.renderers import BaseRenderer
from djangorestframework.utils import reverse
from djangorestframework.views import View
from djangorestframework import status
@ -61,7 +61,7 @@ class PygmentsRoot(View):
Return a list of all currently existing snippets.
"""
unique_ids = [os.path.split(f)[1] for f in list_dir_sorted_by_ctime(HIGHLIGHTED_CODE_DIR)]
return Response([reverse('pygments-instance', args=[unique_id]) for unique_id in unique_ids])
return Response([reverse('pygments-instance', request, args=[unique_id]) for unique_id in unique_ids])
def post(self, request):
"""
@ -81,8 +81,8 @@ class PygmentsRoot(View):
remove_oldest_files(HIGHLIGHTED_CODE_DIR, MAX_FILES)
self.headers['Location'] = reverse('pygments-instance', args=[unique_id])
return Response(status=status.HTTP_201_CREATED)
location = reverse('pygments-instance', request, args=[unique_id])
return Response(status=status.HTTP_201_CREATED, headers={'Location': location})
class PygmentsInstance(View):
@ -98,7 +98,7 @@ class PygmentsInstance(View):
"""
pathname = os.path.join(HIGHLIGHTED_CODE_DIR, unique_id)
if not os.path.exists(pathname):
return Response(status.HTTP_404_NOT_FOUND)
return Response(status=status.HTTP_404_NOT_FOUND)
return Response(open(pathname, 'r').read())
def delete(self, request, unique_id):
@ -107,6 +107,7 @@ class PygmentsInstance(View):
"""
pathname = os.path.join(HIGHLIGHTED_CODE_DIR, unique_id)
if not os.path.exists(pathname):
return Response(status.HTTP_404_NOT_FOUND)
return Response(os.remove(pathname))
return Response(status=status.HTTP_404_NOT_FOUND)
os.remove(pathname)
return Response()

View File

@ -1,5 +1,4 @@
from django.core.urlresolvers import reverse
from djangorestframework.utils import reverse
from djangorestframework.views import View
from djangorestframework.response import Response
from djangorestframework import status
@ -14,9 +13,12 @@ class ExampleView(View):
def get(self, request):
"""
Handle GET requests, returning a list of URLs pointing to 3 other views.
Handle GET requests, returning a list of URLs pointing to
three other views.
"""
return Response({"Some other resources": [reverse('another-example', kwargs={'num':num}) for num in range(3)]})
urls = [reverse('another-example', request, kwargs={'num': num})
for num in range(3)]
return Response({"Some other resources": urls})
class AnotherExampleView(View):
@ -32,7 +34,7 @@ class AnotherExampleView(View):
Returns a simple string indicating which view the GET request was for.
"""
if int(num) > 2:
return Response(status.HTTP_404_NOT_FOUND)
return Response(status=status.HTTP_404_NOT_FOUND)
return Response("GET request to AnotherExampleResource %s" % num)
def post(self, request, num):
@ -41,5 +43,5 @@ class AnotherExampleView(View):
Returns a simple string indicating what content was supplied.
"""
if int(num) > 2:
return Response(status.HTTP_404_NOT_FOUND)
return Response(status=status.HTTP_404_NOT_FOUND)
return Response("POST request to AnotherExampleResource %s, with content: %s" % (num, repr(self.CONTENT)))

View File

@ -1,40 +1,67 @@
"""The root view for the examples provided with Django REST framework"""
from django.core.urlresolvers import reverse
from djangorestframework.utils import reverse
from djangorestframework.views import View
from djangorestframework.response import Response
class Sandbox(View):
"""This is the sandbox for the examples provided with [Django REST framework](http://django-rest-framework.org).
"""
This is the sandbox for the examples provided with
[Django REST framework][1].
These examples are provided to help you get a better idea of some of the features of RESTful APIs created using the framework.
These examples are provided to help you get a better idea of some of the
features of RESTful APIs created using the framework.
All the example APIs allow anonymous access, and can be navigated either through the browser or from the command line...
All the example APIs allow anonymous access, and can be navigated either
through the browser or from the command line.
bash: curl -X GET http://api.django-rest-framework.org/ # (Use default renderer)
bash: curl -X GET http://api.django-rest-framework.org/ -H 'Accept: text/plain' # (Use plaintext documentation renderer)
For example, to get the default representation using curl:
bash: curl -X GET http://rest.ep.io/
Or, to get the plaintext documentation represention:
bash: curl -X GET http://rest.ep.io/ -H 'Accept: text/plain'
The examples provided:
1. A basic example using the [Resource](http://django-rest-framework.org/library/resource.html) class.
2. A basic example using the [ModelResource](http://django-rest-framework.org/library/modelresource.html) class.
3. An basic example using Django 1.3's [class based views](http://docs.djangoproject.com/en/dev/topics/class-based-views/) and djangorestframework's [RendererMixin](http://django-rest-framework.org/library/renderers.html).
1. A basic example using the [Resource][2] class.
2. A basic example using the [ModelResource][3] class.
3. An basic example using Django 1.3's [class based views][4] and
djangorestframework's [RendererMixin][5].
4. A generic object store API.
5. A code highlighting API.
6. A blog posts and comments API.
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.
[1]: http://django-rest-framework.org
[2]: http://django-rest-framework.org/library/resource.html
[3]: http://django-rest-framework.org/library/modelresource.html
[4]: http://docs.djangoproject.com/en/dev/topics/class-based-views/
[5]: http://django-rest-framework.org/library/renderers.html
"""
def get(self, request):
return Response([{'name': 'Simple Resource example', 'url': reverse('example-resource')},
{'name': 'Simple ModelResource example', 'url': reverse('model-resource-root')},
{'name': 'Simple Mixin-only example', 'url': reverse('mixin-view')},
{'name': 'Object store API', 'url': reverse('object-store-root')},
{'name': 'Code highlighting API', 'url': reverse('pygments-root')},
{'name': 'Blog posts API', 'url': reverse('blog-posts-root')},
{'name': 'Permissions example', 'url': reverse('permissions-example')},
{'name': 'Simple request mixin example', 'url': reverse('request-example')}
])
return Response([
{'name': 'Simple Resource example',
'url': reverse('example-resource', request)},
{'name': 'Simple ModelResource example',
'url': reverse('model-resource-root', request)},
{'name': 'Simple Mixin-only example',
'url': reverse('mixin-view', request)},
{'name': 'Object store API'
'url': reverse('object-store-root', request)},
{'name': 'Code highlighting API',
'url': reverse('pygments-root', request)},
{'name': 'Blog posts API',
'url': reverse('blog-posts-root', request)},
{'name': 'Permissions example',
'url': reverse('permissions-example', request)},
{'name': 'Simple request mixin example',
'url': reverse('request-example', request)}
])