mirror of
				https://github.com/encode/django-rest-framework.git
				synced 2025-10-31 07:57:55 +03:00 
			
		
		
		
	Merging master into develop
This commit is contained in:
		
							parent
							
								
									21fcd3a906
								
							
						
					
					
						commit
						af9e4f69d7
					
				
							
								
								
									
										2
									
								
								AUTHORS
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								AUTHORS
									
									
									
									
									
								
							|  | @ -31,6 +31,8 @@ Ben Timby <btimby> | ||||||
| Michele Lazzeri <michelelazzeri-nextage> | Michele Lazzeri <michelelazzeri-nextage> | ||||||
| Camille Harang <mammique> | Camille Harang <mammique> | ||||||
| Paul Oswald <poswald> | Paul Oswald <poswald> | ||||||
|  | Sean C. Farley <scfarley> | ||||||
|  | Daniel Izquierdo <izquierdo> | ||||||
| 
 | 
 | ||||||
| THANKS TO: | THANKS TO: | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,16 +1,19 @@ | ||||||
| Release Notes | Release Notes | ||||||
| ============= | ============= | ||||||
| 
 | 
 | ||||||
| development | 0.3.3 | ||||||
| ----------- | ----- | ||||||
| 
 | 
 | ||||||
| * Added DjangoModelPermissions class to support `django.contrib.auth` style permissions. | * Added DjangoModelPermissions class to support `django.contrib.auth` style permissions. | ||||||
| * Use `staticfiles` for css files. | * Use `staticfiles` for css files. | ||||||
|   - Easier to override.  Won't conflict with customised admin styles (eg grappelli) |   - 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. | * Drop implied 'pk' filter if last arg in urlconf is unnamed. | ||||||
|   - Too magical.  Explict is better than implicit. |   - Too magical.  Explict is better than implicit. | ||||||
| * Saner template variable autoescaping. | * Saner template variable autoescaping. | ||||||
| * Tider setup.py | * Tider setup.py | ||||||
|  | * Updated for URLObject 2.0 | ||||||
| * Bugfixes: | * Bugfixes: | ||||||
|   - Bug with PerUserThrottling when user contains unicode chars. |   - Bug with PerUserThrottling when user contains unicode chars. | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,3 +1,3 @@ | ||||||
| __version__ = '0.3.3-dev' | __version__ = '0.3.3' | ||||||
| 
 | 
 | ||||||
| VERSION = __version__  # synonym | VERSION = __version__  # synonym | ||||||
|  |  | ||||||
|  | @ -497,12 +497,12 @@ class PaginatorMixin(object): | ||||||
|         """ |         """ | ||||||
|         Constructs a url used for getting the next/previous urls |         Constructs a url used for getting the next/previous urls | ||||||
|         """ |         """ | ||||||
|         url = URLObject.parse(self.request.get_full_path()) |         url = URLObject(self.request.get_full_path()) | ||||||
|         url = url.set_query_param('page', page_number) |         url = url.set_query_param('page', str(page_number)) | ||||||
| 
 | 
 | ||||||
|         limit = self.get_limit() |         limit = self.get_limit() | ||||||
|         if limit != self.limit: |         if limit != self.limit: | ||||||
|             url = url.add_query_param('limit', limit) |             url = url.set_query_param('limit', str(limit)) | ||||||
| 
 | 
 | ||||||
|         return url |         return url | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -379,7 +379,7 @@ class DocumentingHTMLRenderer(DocumentingTemplateRenderer): | ||||||
| 
 | 
 | ||||||
|     media_type = 'text/html' |     media_type = 'text/html' | ||||||
|     format = 'html' |     format = 'html' | ||||||
|     template = 'renderer.html' |     template = 'djangorestframework/api.html' | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class DocumentingXHTMLRenderer(DocumentingTemplateRenderer): | class DocumentingXHTMLRenderer(DocumentingTemplateRenderer): | ||||||
|  | @ -391,7 +391,7 @@ class DocumentingXHTMLRenderer(DocumentingTemplateRenderer): | ||||||
| 
 | 
 | ||||||
|     media_type = 'application/xhtml+xml' |     media_type = 'application/xhtml+xml' | ||||||
|     format = 'xhtml' |     format = 'xhtml' | ||||||
|     template = 'renderer.html' |     template = 'djangorestframework/api.html' | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class DocumentingPlainTextRenderer(DocumentingTemplateRenderer): | class DocumentingPlainTextRenderer(DocumentingTemplateRenderer): | ||||||
|  | @ -403,7 +403,7 @@ class DocumentingPlainTextRenderer(DocumentingTemplateRenderer): | ||||||
| 
 | 
 | ||||||
|     media_type = 'text/plain' |     media_type = 'text/plain' | ||||||
|     format = 'txt' |     format = 'txt' | ||||||
|     template = 'renderer.txt' |     template = 'djangorestframework/api.txt' | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| DEFAULT_RENDERERS = ( | DEFAULT_RENDERERS = ( | ||||||
|  |  | ||||||
|  | @ -1,10 +1,10 @@ | ||||||
| from django import forms | 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 django.db import models | ||||||
| 
 | 
 | ||||||
| from djangorestframework.response import ImmediateResponse | from djangorestframework.response import ImmediateResponse | ||||||
| from djangorestframework.serializer import Serializer, _SkipField | from djangorestframework.serializer import Serializer, _SkipField | ||||||
| from djangorestframework.utils import as_tuple | from djangorestframework.utils import as_tuple, reverse | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class BaseResource(Serializer): | class BaseResource(Serializer): | ||||||
|  | @ -354,7 +354,7 @@ class ModelResource(FormResource): | ||||||
|                         instance_attrs[param] = attr |                         instance_attrs[param] = attr | ||||||
| 
 | 
 | ||||||
|                 try: |                 try: | ||||||
|                     return reverse(self.view_callable[0], kwargs=instance_attrs) |                     return reverse(self.view_callable[0], self.view.request, kwargs=instance_attrs) | ||||||
|                 except NoReverseMatch: |                 except NoReverseMatch: | ||||||
|                     pass |                     pass | ||||||
|         raise _SkipField |         raise _SkipField | ||||||
|  |  | ||||||
|  | @ -40,7 +40,7 @@ class Response(SimpleTemplateResponse): | ||||||
|     _ACCEPT_QUERY_PARAM = '_accept'        # Allow override of Accept header in URL query params |     _ACCEPT_QUERY_PARAM = '_accept'        # Allow override of Accept header in URL query params | ||||||
|     _IGNORE_IE_ACCEPT_HEADER = True |     _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, |         # First argument taken by `SimpleTemplateResponse.__init__` is template_name, | ||||||
|         # which we don't need |         # which we don't need | ||||||
|         super(Response, self).__init__(None, status=status) |         super(Response, self).__init__(None, status=status) | ||||||
|  | @ -50,6 +50,7 @@ class Response(SimpleTemplateResponse): | ||||||
|         self.raw_content = content |         self.raw_content = content | ||||||
|         self.has_content_body = content is not None |         self.has_content_body = content is not None | ||||||
|         self.request = request |         self.request = request | ||||||
|  |         self.headers = headers and headers[:] or [] | ||||||
|         if renderers is not None: |         if renderers is not None: | ||||||
|             self.renderers = renderers |             self.renderers = renderers | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -146,7 +146,7 @@ class Serializer(object): | ||||||
|         # then the second element of the tuple is the fields to |         # then the second element of the tuple is the fields to | ||||||
|         # set on the related serializer |         # set on the related serializer | ||||||
|         if isinstance(info, (list, tuple)): |         if isinstance(info, (list, tuple)): | ||||||
|             class OnTheFlySerializer(Serializer): |             class OnTheFlySerializer(self.__class__): | ||||||
|                 fields = info |                 fields = info | ||||||
|             return OnTheFlySerializer |             return OnTheFlySerializer | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -0,0 +1,3 @@ | ||||||
|  | {% extends "djangorestframework/base.html" %} | ||||||
|  | 
 | ||||||
|  | {# Override this template in your own templates directory to customize #} | ||||||
|  | @ -7,26 +7,34 @@ | ||||||
| <html xmlns="http://www.w3.org/1999/xhtml"> | <html xmlns="http://www.w3.org/1999/xhtml"> | ||||||
|   	<head> |   	<head> | ||||||
|       	<link rel="stylesheet" type="text/css" href='{% get_static_prefix %}djangorestframework/css/style.css'/> |       	<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> |   	</head> | ||||||
|   <body> |   <body class="{% block bodyclass %}{% endblock %}"> | ||||||
|   <div id="container"> |   <div id="container"> | ||||||
| 
 | 
 | ||||||
| 	<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> <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> | ||||||
| 		<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 %} | ||||||
|  | 		  {% block userlinks %}{% endblock %} | ||||||
| 		</div> | 		</div> | ||||||
|  | 		{% block nav-global %}{% endblock %} | ||||||
| 	</div> | 	</div> | ||||||
| 
 | 
 | ||||||
| 	<div class="breadcrumbs"> | 	<div class="breadcrumbs"> | ||||||
|  | 	{% block breadcrumbs %} | ||||||
| 	{% for breadcrumb_name, breadcrumb_url in breadcrumblist %} | 	{% for breadcrumb_name, breadcrumb_url in breadcrumblist %} | ||||||
|     <a href="{{ breadcrumb_url }}">{{ breadcrumb_name }}</a> {% if not forloop.last %}›{% endif %} |     <a href="{{ breadcrumb_url }}">{{ breadcrumb_name }}</a> {% if not forloop.last %}›{% endif %} | ||||||
|     {% endfor %} |     {% endfor %} | ||||||
|  |     {% endblock %} | ||||||
|     </div> |     </div> | ||||||
| 
 | 
 | ||||||
|  |     <!-- Content --> | ||||||
|     <div id="content" class="{% block coltype %}colM{% endblock %}"> |     <div id="content" class="{% block coltype %}colM{% endblock %}"> | ||||||
| 
 | 
 | ||||||
| 		{% if 'OPTIONS' in allowed_methods %} | 		{% if 'OPTIONS' in allowed_methods %} | ||||||
|  | @ -123,7 +131,12 @@ | ||||||
| 
 | 
 | ||||||
| 	{% endif %} | 	{% endif %} | ||||||
| 	</div> | 	</div> | ||||||
|  | 	<!-- END content-main --> | ||||||
|  | 
 | ||||||
| 	</div> | 	</div> | ||||||
|  | 	<!-- END Content --> | ||||||
|  | 
 | ||||||
|  |     {% block footer %}<div id="footer"></div>{% endblock %} | ||||||
| 	</div> | 	</div> | ||||||
|   </body> |   </body> | ||||||
| </html> | </html> | ||||||
|  | @ -4,8 +4,7 @@ register = Library() | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def add_query_param(url, param): | def add_query_param(url, param): | ||||||
|     (key, sep, val) = param.partition('=') |     return unicode(URLObject(url).with_query(param)) | ||||||
|     return unicode(URLObject.parse(url) & (key, val)) |  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| register.filter('add_query_param', add_query_param) | register.filter('add_query_param', add_query_param) | ||||||
|  |  | ||||||
|  | @ -1,8 +1,8 @@ | ||||||
| from django.conf.urls.defaults import patterns, url | from django.conf.urls.defaults import patterns, url | ||||||
| from django.core.urlresolvers import reverse |  | ||||||
| from django.test import TestCase | from django.test import TestCase | ||||||
| from django.utils import simplejson as json | from django.utils import simplejson as json | ||||||
| 
 | 
 | ||||||
|  | from djangorestframework.utils import reverse | ||||||
| from djangorestframework.views import View | from djangorestframework.views import View | ||||||
| from djangorestframework.response import Response | from djangorestframework.response import Response | ||||||
| 
 | 
 | ||||||
|  | @ -12,7 +12,7 @@ class MockView(View): | ||||||
|     permissions = () |     permissions = () | ||||||
| 
 | 
 | ||||||
|     def get(self, request): |     def get(self, request): | ||||||
|         return Response(reverse('another')) |         return Response(reverse('another', request)) | ||||||
| 
 | 
 | ||||||
| urlpatterns = patterns('', | urlpatterns = patterns('', | ||||||
|     url(r'^$', MockView.as_view()), |     url(r'^$', MockView.as_view()), | ||||||
|  |  | ||||||
|  | @ -1,6 +1,7 @@ | ||||||
|  | import django | ||||||
| from django.utils.encoding import smart_unicode | from django.utils.encoding import smart_unicode | ||||||
| from django.utils.xmlutils import SimplerXMLGenerator | 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 django.conf import settings | ||||||
| 
 | 
 | ||||||
| from djangorestframework.compat import StringIO | from djangorestframework.compat import StringIO | ||||||
|  | @ -180,3 +181,21 @@ class XMLRenderer(): | ||||||
| 
 | 
 | ||||||
| def dict2xml(input): | def dict2xml(input): | ||||||
|     return XMLRenderer().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)) | ||||||
|  |  | ||||||
|  | @ -12,7 +12,7 @@ import base64 | ||||||
| # be making settings changes in order to accomodate django-rest-framework | # be making settings changes in order to accomodate django-rest-framework | ||||||
| @csrf_protect | @csrf_protect | ||||||
| @never_cache | @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, |           redirect_field_name=REDIRECT_FIELD_NAME, | ||||||
|           authentication_form=AuthenticationForm): |           authentication_form=AuthenticationForm): | ||||||
|     """Displays the login form and handles the login action.""" |     """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)) |     }, 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) |     return logout(request, next_page, template_name, redirect_field_name) | ||||||
|  |  | ||||||
|  | @ -188,22 +188,13 @@ class View(ResourceMixin, RequestMixin, ResponseMixin, AuthMixin, DjangoView): | ||||||
|         Required if you want to do things like set `request.upload_handlers` before |         Required if you want to do things like set `request.upload_handlers` before | ||||||
|         the authentication and dispatch handling is run. |         the authentication and dispatch handling is run. | ||||||
|         """ |         """ | ||||||
|         # Calls to 'reverse' will not be fully qualified unless we set the |         pass | ||||||
|         # 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 |  | ||||||
| 
 | 
 | ||||||
|     def final(self, request, response, *args, **kargs): |     def final(self, request, response, *args, **kargs): | ||||||
|         """ |         """ | ||||||
|         Returns an `HttpResponse`. This method is a hook for any code that needs to run |         Returns an `HttpResponse`. This method is a hook for any code that needs to run | ||||||
|         after everything else in the view. |         after everything else in the view. | ||||||
|         """ |         """ | ||||||
|         # Restore script_prefix. |  | ||||||
|         set_script_prefix(self.orig_prefix) |  | ||||||
| 
 |  | ||||||
|         # Always add these headers. |         # Always add these headers. | ||||||
|         response['Allow'] = ', '.join(allowed_methods(self)) |         response['Allow'] = ', '.join(allowed_methods(self)) | ||||||
|         # sample to allow caching using Vary http header |         # sample to allow caching using Vary http header | ||||||
|  |  | ||||||
							
								
								
									
										47
									
								
								docs/howto/reverse.rst
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								docs/howto/reverse.rst
									
									
									
									
									
										Normal 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 | ||||||
|  | @ -3,45 +3,58 @@ | ||||||
| Setup | 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,  | Django REST framework requires `django.contrib.staticfiles`_ to serve it's css. | ||||||
| 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 you're using Django 1.2 you'll need to use the seperate | ||||||
| `if using the Django admin <https://docs.djangoproject.com/en/dev/howto/deployment/modpython/#serving-the-admin-files>`_. | `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 | 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  | If markdown is installed your :class:`.Resource` descriptions can include | ||||||
| <http://daringfireball.net/projects/markdown/syntax>`_ which will be rendered by the HTML documenting renderer. | `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 | YAML support is optional, and requires `PyYAML`_. | ||||||
| login and logout views:: | 
 | ||||||
|  | 
 | ||||||
|  | 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 |     from django.conf.urls.defaults import patterns | ||||||
| 
 | 
 | ||||||
|  | @ -51,3 +64,9 @@ login and logout views:: | ||||||
|         (r'^accounts/logout/$', 'api_logout'), |         (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 | ||||||
|  | @ -40,8 +40,11 @@ Requirements | ||||||
| ------------ | ------------ | ||||||
| 
 | 
 | ||||||
| * Python (2.5, 2.6, 2.7 supported) | * 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 | Installation | ||||||
| ------------ | ------------ | ||||||
|  | @ -54,8 +57,6 @@ Or get the latest development version using git:: | ||||||
| 
 | 
 | ||||||
|     git clone git@github.com:tomchristie/django-rest-framework.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 | Setup | ||||||
| ----- | ----- | ||||||
| 
 | 
 | ||||||
|  | @ -114,3 +115,8 @@ Indices and tables | ||||||
| * :ref:`modindex` | * :ref:`modindex` | ||||||
| * :ref:`search` | * :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
									
								
							
							
						
						
									
										5
									
								
								docs/library/utils.rst
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,5 @@ | ||||||
|  | :mod:`utils` | ||||||
|  | ============== | ||||||
|  | 
 | ||||||
|  | .. automodule:: utils | ||||||
|  |    :members: | ||||||
|  | @ -1,5 +1,5 @@ | ||||||
| from django.core.urlresolvers import reverse |  | ||||||
| from djangorestframework.resources import ModelResource | from djangorestframework.resources import ModelResource | ||||||
|  | from djangorestframework.utils import reverse | ||||||
| from blogpost.models import BlogPost, Comment | from blogpost.models import BlogPost, Comment | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -12,7 +12,7 @@ class BlogPostResource(ModelResource): | ||||||
|     ordering = ('-created',) |     ordering = ('-created',) | ||||||
| 
 | 
 | ||||||
|     def comments(self, instance): |     def comments(self, instance): | ||||||
|         return reverse('comments', kwargs={'blogpost': instance.key}) |         return reverse('comments', request, kwargs={'blogpost': instance.key}) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class CommentResource(ModelResource): | class CommentResource(ModelResource): | ||||||
|  | @ -24,4 +24,4 @@ class CommentResource(ModelResource): | ||||||
|     ordering = ('-created',) |     ordering = ('-created',) | ||||||
| 
 | 
 | ||||||
|     def blogpost(self, instance): |     def blogpost(self, instance): | ||||||
|         return reverse('blog-post', kwargs={'key': instance.blogpost.key}) |         return reverse('blog-post', request, kwargs={'key': instance.blogpost.key}) | ||||||
|  |  | ||||||
|  | @ -1,12 +1,11 @@ | ||||||
| """Test a range of REST API usage of the example application. | """Test a range of REST API usage of the example application. | ||||||
| """ | """ | ||||||
| 
 | 
 | ||||||
| from django.core.urlresolvers import reverse |  | ||||||
| from django.test import TestCase | from django.test import TestCase | ||||||
| from django.core.urlresolvers import reverse |  | ||||||
| from django.utils import simplejson as json | from django.utils import simplejson as json | ||||||
| 
 | 
 | ||||||
| from djangorestframework.compat import RequestFactory | from djangorestframework.compat import RequestFactory | ||||||
|  | from djangorestframework.utils import reverse | ||||||
| from djangorestframework.views import InstanceModelView, ListOrCreateModelView | from djangorestframework.views import InstanceModelView, ListOrCreateModelView | ||||||
| 
 | 
 | ||||||
| from blogpost import models, urls | from blogpost import models, urls | ||||||
|  |  | ||||||
|  | @ -2,9 +2,9 @@ from djangorestframework.compat import View  # Use Django 1.3's django.views.gen | ||||||
| from djangorestframework.mixins import ResponseMixin | from djangorestframework.mixins import ResponseMixin | ||||||
| from djangorestframework.renderers import DEFAULT_RENDERERS | from djangorestframework.renderers import DEFAULT_RENDERERS | ||||||
| from djangorestframework.response import Response | from djangorestframework.response import Response | ||||||
|  | from djangorestframework.utils import reverse | ||||||
| 
 | 
 | ||||||
| from django.conf.urls.defaults import patterns, url | from django.conf.urls.defaults import patterns, url | ||||||
| from django.core.urlresolvers import reverse |  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class ExampleView(ResponseMixin, View): | class ExampleView(ResponseMixin, View): | ||||||
|  | @ -14,7 +14,7 @@ class ExampleView(ResponseMixin, View): | ||||||
| 
 | 
 | ||||||
|     def get(self, request): |     def get(self, request): | ||||||
|         response = Response({'description': 'Some example content', |         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) |         self.response = self.prepare_response(response) | ||||||
|         return self.response |         return self.response | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,6 +1,6 @@ | ||||||
| from django.conf import settings | from django.conf import settings | ||||||
| from django.core.urlresolvers import reverse |  | ||||||
| 
 | 
 | ||||||
|  | from djangorestframework.utils import reverse | ||||||
| from djangorestframework.views import View | from djangorestframework.views import View | ||||||
| from djangorestframework.response import Response | from djangorestframework.response import Response | ||||||
| from djangorestframework import status | 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('.')] |         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], |         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)] |                                                              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): |     def post(self, request): | ||||||
|         """ |         """ | ||||||
|  | @ -51,8 +51,8 @@ class ObjectStoreRoot(View): | ||||||
|         pathname = os.path.join(OBJECT_STORE_DIR, key) |         pathname = os.path.join(OBJECT_STORE_DIR, key) | ||||||
|         pickle.dump(self.CONTENT, open(pathname, 'wb')) |         pickle.dump(self.CONTENT, open(pathname, 'wb')) | ||||||
|         remove_oldest_files(OBJECT_STORE_DIR, MAX_FILES) |         remove_oldest_files(OBJECT_STORE_DIR, MAX_FILES) | ||||||
|         self.headers['Location'] = reverse('stored-object', kwargs={'key':key}) |         url = reverse('stored-object', request, kwargs={'key':key}) | ||||||
|         return Response(self.CONTENT, status=status.HTTP_201_CREATED) |         return Response(self.CONTENT, status.HTTP_201_CREATED, {'Location': url}) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class StoredObject(View): | class StoredObject(View): | ||||||
|  |  | ||||||
|  | @ -1,7 +1,7 @@ | ||||||
| from djangorestframework.views import View | from djangorestframework.views import View | ||||||
| from djangorestframework.response import Response | from djangorestframework.response import Response | ||||||
| from djangorestframework.permissions import PerUserThrottling, IsAuthenticated | from djangorestframework.permissions import PerUserThrottling, IsAuthenticated | ||||||
| from django.core.urlresolvers import reverse | from djangorestframework.utils import reverse | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class PermissionsExampleView(View): | class PermissionsExampleView(View): | ||||||
|  | @ -13,11 +13,11 @@ class PermissionsExampleView(View): | ||||||
|         return Response([ |         return Response([ | ||||||
|             { |             { | ||||||
|                 'name': 'Throttling Example', |                 'name': 'Throttling Example', | ||||||
|                 'url': reverse('throttled-resource') |                 'url': reverse('throttled-resource', request) | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 'name': 'Logged in example', |                 'name': 'Logged in example', | ||||||
|                 'url': reverse('loggedin-resource') |                 'url': reverse('loggedin-resource', request) | ||||||
|             }, |             }, | ||||||
|         ]) |         ]) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,10 +1,10 @@ | ||||||
| from __future__ import with_statement  # for python 2.5 | from __future__ import with_statement  # for python 2.5 | ||||||
| from django.conf import settings | from django.conf import settings | ||||||
| from django.core.urlresolvers import reverse |  | ||||||
| 
 | 
 | ||||||
| from djangorestframework.resources import FormResource | from djangorestframework.resources import FormResource | ||||||
| from djangorestframework.response import Response | from djangorestframework.response import Response | ||||||
| from djangorestframework.renderers import BaseRenderer | from djangorestframework.renderers import BaseRenderer | ||||||
|  | from djangorestframework.utils import reverse | ||||||
| from djangorestframework.views import View | from djangorestframework.views import View | ||||||
| from djangorestframework import status | from djangorestframework import status | ||||||
| 
 | 
 | ||||||
|  | @ -61,7 +61,7 @@ class PygmentsRoot(View): | ||||||
|         Return a list of all currently existing snippets. |         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)] |         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): |     def post(self, request): | ||||||
|         """ |         """ | ||||||
|  | @ -81,8 +81,8 @@ class PygmentsRoot(View): | ||||||
| 
 | 
 | ||||||
|         remove_oldest_files(HIGHLIGHTED_CODE_DIR, MAX_FILES) |         remove_oldest_files(HIGHLIGHTED_CODE_DIR, MAX_FILES) | ||||||
| 
 | 
 | ||||||
|         self.headers['Location'] = reverse('pygments-instance', args=[unique_id]) |         location = reverse('pygments-instance', request, args=[unique_id]) | ||||||
|         return Response(status=status.HTTP_201_CREATED) |         return Response(status=status.HTTP_201_CREATED, headers={'Location': location}) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class PygmentsInstance(View): | class PygmentsInstance(View): | ||||||
|  | @ -98,7 +98,7 @@ class PygmentsInstance(View): | ||||||
|         """ |         """ | ||||||
|         pathname = os.path.join(HIGHLIGHTED_CODE_DIR, unique_id) |         pathname = os.path.join(HIGHLIGHTED_CODE_DIR, unique_id) | ||||||
|         if not os.path.exists(pathname): |         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()) |         return Response(open(pathname, 'r').read()) | ||||||
| 
 | 
 | ||||||
|     def delete(self, request, unique_id): |     def delete(self, request, unique_id): | ||||||
|  | @ -107,6 +107,7 @@ class PygmentsInstance(View): | ||||||
|         """ |         """ | ||||||
|         pathname = os.path.join(HIGHLIGHTED_CODE_DIR, unique_id) |         pathname = os.path.join(HIGHLIGHTED_CODE_DIR, unique_id) | ||||||
|         if not os.path.exists(pathname): |         if not os.path.exists(pathname): | ||||||
|             return Response(status.HTTP_404_NOT_FOUND) |             return Response(status=status.HTTP_404_NOT_FOUND) | ||||||
|         return Response(os.remove(pathname)) |         os.remove(pathname) | ||||||
|  |         return Response() | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,5 +1,4 @@ | ||||||
| from django.core.urlresolvers import reverse | from djangorestframework.utils import reverse | ||||||
| 
 |  | ||||||
| from djangorestframework.views import View | from djangorestframework.views import View | ||||||
| from djangorestframework.response import Response | from djangorestframework.response import Response | ||||||
| from djangorestframework import status | from djangorestframework import status | ||||||
|  | @ -14,9 +13,12 @@ class ExampleView(View): | ||||||
| 
 | 
 | ||||||
|     def get(self, request): |     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): | class AnotherExampleView(View): | ||||||
|  | @ -32,7 +34,7 @@ class AnotherExampleView(View): | ||||||
|         Returns a simple string indicating which view the GET request was for. |         Returns a simple string indicating which view the GET request was for. | ||||||
|         """ |         """ | ||||||
|         if int(num) > 2: |         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) |         return Response("GET request to AnotherExampleResource %s" % num) | ||||||
| 
 | 
 | ||||||
|     def post(self, request, num): |     def post(self, request, num): | ||||||
|  | @ -41,5 +43,5 @@ class AnotherExampleView(View): | ||||||
|         Returns a simple string indicating what content was supplied. |         Returns a simple string indicating what content was supplied. | ||||||
|         """ |         """ | ||||||
|         if int(num) > 2: |         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))) |         return Response("POST request to AnotherExampleResource %s, with content: %s" % (num, repr(self.CONTENT))) | ||||||
|  |  | ||||||
|  | @ -1,40 +1,67 @@ | ||||||
| """The root view for the examples provided with Django REST framework""" | """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.views import View | ||||||
| from djangorestframework.response import Response | from djangorestframework.response import Response | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class Sandbox(View): | 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) |     For example, to get the default representation using curl: | ||||||
|         bash: curl -X GET http://api.django-rest-framework.org/ -H 'Accept: text/plain'   # (Use plaintext documentation renderer) | 
 | ||||||
|  |         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: |     The examples provided: | ||||||
| 
 | 
 | ||||||
|     1. A basic example using the [Resource](http://django-rest-framework.org/library/resource.html) class. |     1. A basic example using the [Resource][2] class. | ||||||
|     2. A basic example using the [ModelResource](http://django-rest-framework.org/library/modelresource.html) class. |     2. A basic example using the [ModelResource][3] 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). |     3. An basic example using Django 1.3's [class based views][4] and | ||||||
|  |        djangorestframework's [RendererMixin][5]. | ||||||
|     4. A generic object store API. |     4. A generic object store API. | ||||||
|     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. |     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): |     def get(self, request): | ||||||
|         return Response([{'name': 'Simple Resource example', 'url': reverse('example-resource')}, |         return Response([ | ||||||
|                 {'name': 'Simple ModelResource example', 'url': reverse('model-resource-root')}, |             {'name': 'Simple Resource example', | ||||||
|                 {'name': 'Simple Mixin-only example', 'url': reverse('mixin-view')}, |              'url': reverse('example-resource', request)}, | ||||||
|                 {'name': 'Object store API', 'url': reverse('object-store-root')}, |             {'name': 'Simple ModelResource example', | ||||||
|                 {'name': 'Code highlighting API', 'url': reverse('pygments-root')}, |              'url': reverse('model-resource-root', request)}, | ||||||
|                 {'name': 'Blog posts API', 'url': reverse('blog-posts-root')}, |             {'name': 'Simple Mixin-only example', | ||||||
|                 {'name': 'Permissions example', 'url': reverse('permissions-example')}, |              'url': reverse('mixin-view', request)}, | ||||||
|                 {'name': 'Simple request mixin example', 'url': reverse('request-example')} |             {'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)} | ||||||
|         ]) |         ]) | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user