diff --git a/docs/topics/browsable-api.md b/docs/topics/browsable-api.md
new file mode 100644
index 00000000..6d2d2a37
--- /dev/null
+++ b/docs/topics/browsable-api.md
@@ -0,0 +1,86 @@
+# Working with the Browsable API
+
+API may stand for Application *Programming* Interface, but humans have to be able to read the APIs, too; someone has to do the programming. Django REST Framework supports generating human-friendly HTML output for each resource when the `HTML` format is requested. These pages allow for easy browsing of resources, as well as forms for submitting data to the resources using `POST`, `PUT`, and `DELETE`.
+
+## URLs
+
+If you include fully-qualified URLs in your resource output, they will be 'urlized' and made clickable for easy browsing by humans. The `djangorestframework` package includes a [`reverse`](../api-guide/reverse.md) helper for this purpose.
+
+
+## Formats
+
+By default, the API will return the format specified by the headers, which in the case of the browser is HTML. The format can be specified using `?format=` in the request, so you can look at the raw JSON response in a browser by adding `?format=json` to the URL. There are helpful extensions for viewing JSON in [Firefox](https://addons.mozilla.org/en-US/firefox/addon/jsonview/) and [Chrome](https://chrome.google.com/webstore/detail/chklaanhfefbnpoihckbnefhakgolnmc).
+
+
+## Customizing
+
+To customize the look-and-feel, create a template called `api.html` and add it to your project, eg: `templates/djangorestframework/api.html`, that extends the `djangorestframework/base.html` template.
+
+The included browsable API template is built with [Bootstrap (2.1.1)](http://getbootstrap.com), making it easy to customize the look-and-feel.
+
+### Theme
+
+To replace the theme wholesale, add a `bootstrap_theme` block to your `api.html` and insert a `link` to the desired Bootstrap theme css file. This will completely replace the included theme.
+
+ {% block bootstrap_theme %}
+
+ {% endblock %}
+
+A suitable replacement theme can be generated using Bootstrap's [Customize Tool](http://twitter.github.com/bootstrap/customize.html#variables). Also, there are pre-made themes available at [Bootswatch](http://bootswatch.com/), which are even hosted by [Bootstrap CDN](http://www.bootstrapcdn.com/). To use any of the Bootswatch themes, simply download the theme's `bootstrap.min.css` file, add it to your project, and replace the default one as described above.
+
+You can also change the navbar variant, which by default is `navbar-inverse`, using the `bootstrap_navbar_variant` block. The empty `{% block bootstrap_navbar_variant %}{% endblock %}` will use the original Bootstrap navbar style.
+
+For more specific CSS tweaks, use the `extra_style` block instead.
+
+
+### Blocks
+
+All of the blocks available in the browsable API base template that can be used in your `api.html`.
+
+* `blockbots` - `` tag that blocks crawlers
+* `bodyclass` - (empty) class attribute for the ``
+* `bootstrap_theme` - CSS for the Bootstrap theme
+* `bootstrap_navbar_variant` - CSS class for the navbar
+* `branding` - section of the navbar, see [Bootstrap components](http://twitter.github.com/bootstrap/components.html#navbar)
+* `breadcrumbs` - Links showing resource nesting, allowing the user to go back up the resources. It's recommended to preserve these, but they can be overridden using the breadcrumbs block.
+* `extrastyle` - (empty) extra CSS for the page
+* `extrahead` - (empty) extra markup for the page ``
+* `footer` - Any copyright notices or similar footer materials can go here (by default right-aligned)
+* `global_heading` - (empty) Use to insert content below the header but before the breadcrumbs.
+* `title` - title of the page
+* `userlinks` - This is a list of links on the right of the header, by default containing login/logout links. To add links instead of replace, use {{ block.super }} to preserve the authentication links.
+
+#### Components
+
+All of the [Bootstrap components](http://twitter.github.com/bootstrap/components.html) are available.
+
+##### Tooltips
+
+The browsable API makes use of the Bootstrap tooltips component. Any element with the `js-tooltip` class and a `title` attribute has that title content displayed in a tooltip on hover after a 1000ms delay.
+
+
+### Advanced Customization
+
+#### Context
+
+The context that's available to the template:
+
+* `allowed_methods` : A list of methods allowed by the resource
+* `api_settings` : The API settings
+* `available_formats` : A list of formats allowed by the resource
+* `breadcrumblist` : The list of links following the chain of nested resources
+* `content` : The content of the API response
+* `description` : The description of the resource, generated from its docstring
+* `name` : The name of the resource
+* `post_form` : A form instance for use by the POST form (if allowed)
+* `put_form` : A form instance for use by the PUT form (if allowed)
+* `request` : The request object
+* `response` : The response object
+* `version` : The version of Django REST Framework
+* `view` : The view handling the request
+* `FORMAT_PARAM` : self._FORMAT_QUERY_PARAM
+* `METHOD_PARAM` : getattr(self.view, '_METHOD_PARAM', None)
+
+#### Not using base.html
+
+For more advanced customization, such as not having a Bootstrap basis or tighter integration with the rest of your site, you can simply choose not to have `api.html` extend `base.html`. Then the page content and capabilities are entirely up to you.
\ No newline at end of file
diff --git a/docs/tutorial/2-requests-and-responses.md b/docs/tutorial/2-requests-and-responses.md
index 89f92c4b..2c11d5ef 100644
--- a/docs/tutorial/2-requests-and-responses.md
+++ b/docs/tutorial/2-requests-and-responses.md
@@ -133,7 +133,12 @@ Now go and open the API in a web browser, by visiting [http://127.0.0.1:8000/][3
**Note: Right now the Browseable API only works with the CBV's. Need to fix that.**
-**TODO: Describe browseable API awesomeness**
+### Browsability
+
+Because the API chooses a return format based on what the client asks for, it will, by default, return an HTML-formatted representation of the resource when that resource is requested by a browser. This allows for the API to be easily browsable and usable by humans.
+
+See the [browsable api][4] topic for more information about the browsable API feature and how to customize it.
+
## What's next?
@@ -142,4 +147,5 @@ In [tutorial part 3][4], we'll start using class based views, and see how generi
[json-url]: http://example.com/api/items/4.json
[2]: 1-serialization.md
[3]: http://127.0.0.1:8000/
-[4]: 3-class-based-views.md
\ No newline at end of file
+[4]: ../topics/browsable-api.md
+[5]: 3-class-based-views.md
\ No newline at end of file
--
cgit v1.2.3
From 9684b3fe22d731eb84f67877ab94ee74c8761a01 Mon Sep 17 00:00:00 2001
From: Alec Perkins
Date: Sun, 9 Sep 2012 17:07:54 -0400
Subject: Reference-style links. Much cleaner.
---
docs/topics/browsable-api.md | 25 ++++++++++++++++++-------
1 file changed, 18 insertions(+), 7 deletions(-)
(limited to 'docs')
diff --git a/docs/topics/browsable-api.md b/docs/topics/browsable-api.md
index 6d2d2a37..ba1984f7 100644
--- a/docs/topics/browsable-api.md
+++ b/docs/topics/browsable-api.md
@@ -4,19 +4,19 @@ API may stand for Application *Programming* Interface, but humans have to be abl
## URLs
-If you include fully-qualified URLs in your resource output, they will be 'urlized' and made clickable for easy browsing by humans. The `djangorestframework` package includes a [`reverse`](../api-guide/reverse.md) helper for this purpose.
+If you include fully-qualified URLs in your resource output, they will be 'urlized' and made clickable for easy browsing by humans. The `djangorestframework` package includes a [`reverse`][drfreverse] helper for this purpose.
## Formats
-By default, the API will return the format specified by the headers, which in the case of the browser is HTML. The format can be specified using `?format=` in the request, so you can look at the raw JSON response in a browser by adding `?format=json` to the URL. There are helpful extensions for viewing JSON in [Firefox](https://addons.mozilla.org/en-US/firefox/addon/jsonview/) and [Chrome](https://chrome.google.com/webstore/detail/chklaanhfefbnpoihckbnefhakgolnmc).
+By default, the API will return the format specified by the headers, which in the case of the browser is HTML. The format can be specified using `?format=` in the request, so you can look at the raw JSON response in a browser by adding `?format=json` to the URL. There are helpful extensions for viewing JSON in [Firefox][ffjsonview] and [Chrome][chromejsonview].
## Customizing
To customize the look-and-feel, create a template called `api.html` and add it to your project, eg: `templates/djangorestframework/api.html`, that extends the `djangorestframework/base.html` template.
-The included browsable API template is built with [Bootstrap (2.1.1)](http://getbootstrap.com), making it easy to customize the look-and-feel.
+The included browsable API template is built with [Bootstrap (2.1.1)][bootstrap], making it easy to customize the look-and-feel.
### Theme
@@ -26,7 +26,7 @@ To replace the theme wholesale, add a `bootstrap_theme` block to your `api.html`
{% endblock %}
-A suitable replacement theme can be generated using Bootstrap's [Customize Tool](http://twitter.github.com/bootstrap/customize.html#variables). Also, there are pre-made themes available at [Bootswatch](http://bootswatch.com/), which are even hosted by [Bootstrap CDN](http://www.bootstrapcdn.com/). To use any of the Bootswatch themes, simply download the theme's `bootstrap.min.css` file, add it to your project, and replace the default one as described above.
+A suitable replacement theme can be generated using Bootstrap's [Customize Tool][bcustomize]. Also, there are pre-made themes available at [Bootswatch][bswatch]. To use any of the Bootswatch themes, simply download the theme's `bootstrap.min.css` file, add it to your project, and replace the default one as described above.
You can also change the navbar variant, which by default is `navbar-inverse`, using the `bootstrap_navbar_variant` block. The empty `{% block bootstrap_navbar_variant %}{% endblock %}` will use the original Bootstrap navbar style.
@@ -41,7 +41,7 @@ All of the blocks available in the browsable API base template that can be used
* `bodyclass` - (empty) class attribute for the ``
* `bootstrap_theme` - CSS for the Bootstrap theme
* `bootstrap_navbar_variant` - CSS class for the navbar
-* `branding` - section of the navbar, see [Bootstrap components](http://twitter.github.com/bootstrap/components.html#navbar)
+* `branding` - section of the navbar, see [Bootstrap components][bcomponentsnav]
* `breadcrumbs` - Links showing resource nesting, allowing the user to go back up the resources. It's recommended to preserve these, but they can be overridden using the breadcrumbs block.
* `extrastyle` - (empty) extra CSS for the page
* `extrahead` - (empty) extra markup for the page ``
@@ -52,7 +52,7 @@ All of the blocks available in the browsable API base template that can be used
#### Components
-All of the [Bootstrap components](http://twitter.github.com/bootstrap/components.html) are available.
+All of the [Bootstrap components][bcomponents] are available.
##### Tooltips
@@ -83,4 +83,15 @@ The context that's available to the template:
#### Not using base.html
-For more advanced customization, such as not having a Bootstrap basis or tighter integration with the rest of your site, you can simply choose not to have `api.html` extend `base.html`. Then the page content and capabilities are entirely up to you.
\ No newline at end of file
+For more advanced customization, such as not having a Bootstrap basis or tighter integration with the rest of your site, you can simply choose not to have `api.html` extend `base.html`. Then the page content and capabilities are entirely up to you.
+
+
+[drfreverse]: ../api-guide/reverse.md
+[ffjsonview]: https://addons.mozilla.org/en-US/firefox/addon/jsonview/
+[chromejsonview]: https://chrome.google.com/webstore/detail/chklaanhfefbnpoihckbnefhakgolnmc
+[bootstrap]: http://getbootstrap.com
+[bcustomize]: http://twitter.github.com/bootstrap/customize.html#variables
+[bswatch]: http://bootswatch.com/
+[bcomponents]: http://twitter.github.com/bootstrap/components.html
+[bcomponentsnav]: http://twitter.github.com/bootstrap/components.html#navbar
+
--
cgit v1.2.3
From 4cbc53a75d2d30d05f202777d4e1626011c2cb2e Mon Sep 17 00:00:00 2001
From: Alec Perkins
Date: Sun, 9 Sep 2012 17:25:34 -0400
Subject: Whoops, forgot to explain these.
---
docs/topics/browsable-api.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
(limited to 'docs')
diff --git a/docs/topics/browsable-api.md b/docs/topics/browsable-api.md
index ba1984f7..6f8920bb 100644
--- a/docs/topics/browsable-api.md
+++ b/docs/topics/browsable-api.md
@@ -78,8 +78,8 @@ The context that's available to the template:
* `response` : The response object
* `version` : The version of Django REST Framework
* `view` : The view handling the request
-* `FORMAT_PARAM` : self._FORMAT_QUERY_PARAM
-* `METHOD_PARAM` : getattr(self.view, '_METHOD_PARAM', None)
+* `FORMAT_PARAM` : The view can accept a format override
+* `METHOD_PARAM` : The view can accept a method override
#### Not using base.html
--
cgit v1.2.3
From eb761be9d058dbfb9214f200b941496524dc0ded Mon Sep 17 00:00:00 2001
From: Tom Christie
Date: Fri, 14 Sep 2012 12:43:14 +0100
Subject: Flesh out resources/routers part of tutorial
---
docs/api-guide/throttling.md | 5 +-
docs/topics/changelog.md | 107 ++++++++++++++++++++++++
docs/tutorial/6-resource-orientated-projects.md | 37 ++++++--
3 files changed, 141 insertions(+), 8 deletions(-)
create mode 100644 docs/topics/changelog.md
(limited to 'docs')
diff --git a/docs/api-guide/throttling.md b/docs/api-guide/throttling.md
index d1e34dcd..10997801 100644
--- a/docs/api-guide/throttling.md
+++ b/docs/api-guide/throttling.md
@@ -76,7 +76,7 @@ The allowed request rate is determined from one of the following (in order of pr
## UserRateThrottle
-The `UserThrottle` will throttle users to a given rate of requests across the API. The user id is used to generate a unique key to throttle against. Unauthenticted requests will fall back to using the IP address of the incoming request is used to generate a unique key to throttle against.
+The `UserThrottle` will throttle users to a given rate of requests across the API. The user id is used to generate a unique key to throttle against. Unauthenticted requests will fall back to using the IP address of the incoming request to generate a unique key to throttle against.
The allowed request rate is determined from one of the following (in order of preference).
@@ -106,7 +106,7 @@ For example, multiple user throttle rates could be implemented by using the foll
}
}
-`UserThrottle` is suitable if you want a simple global rate restriction per-user.
+`UserThrottle` is suitable if you want simple global rate restrictions per-user.
## ScopedRateThrottle
@@ -124,7 +124,6 @@ For example, given the following views...
throttle_scope = 'contacts'
...
-
class UploadView(APIView):
throttle_scope = 'uploads'
...
diff --git a/docs/topics/changelog.md b/docs/topics/changelog.md
new file mode 100644
index 00000000..a4fd39e2
--- /dev/null
+++ b/docs/topics/changelog.md
@@ -0,0 +1,107 @@
+# Release Notes
+
+## 2.0.0
+
+**TODO:** Explain REST framework 2.0
+
+## 0.4.0
+
+* Supports Django 1.5.
+* Fixes issues with 'HEAD' method.
+* Allow views to specify template used by TemplateRenderer
+* More consistent error responses
+* Some serializer fixes
+* Fix internet explorer ajax behaviour
+* Minor xml and yaml fixes
+* Improve setup (eg use staticfiles, not the defunct ADMIN_MEDIA_PREFIX)
+* Sensible absolute URL generation, not using hacky set_script_prefix
+
+## 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.
+
+## 0.3.2
+
+* Bugfixes:
+ * Fix 403 for POST and PUT from the UI with UserLoggedInAuthentication (#115)
+ * serialize_model method in serializer.py may cause wrong value (#73)
+ * Fix Error when clicking OPTIONS button (#146)
+ * And many other fixes
+* Remove short status codes
+ - Zen of Python: "There should be one-- and preferably only one --obvious way to do it."
+* get_name, get_description become methods on the view - makes them overridable.
+* Improved model mixin API - Hooks for build_query, get_instance_data, get_model, get_queryset, get_ordering
+
+## 0.3.1
+
+* [not documented]
+
+## 0.3.0
+
+* JSONP Support
+* Bugfixes, including support for latest markdown release
+
+## 0.2.4
+
+* Fix broken IsAdminUser permission.
+* OPTIONS support.
+* XMLParser.
+* Drop mentions of Blog, BitBucket.
+
+## 0.2.3
+
+* Fix some throttling bugs.
+* ``X-Throttle`` header on throttling.
+* Support for nesting resources on related models.
+
+## 0.2.2
+
+* Throttling support complete.
+
+## 0.2.1
+
+* Couple of simple bugfixes over 0.2.0
+
+## 0.2.0
+
+* Big refactoring changes since 0.1.0, ask on the discussion group if anything isn't clear.
+ The public API has been massively cleaned up. Expect it to be fairly stable from here on in.
+
+* ``Resource`` becomes decoupled into ``View`` and ``Resource``, your views should now inherit from ``View``, not ``Resource``.
+
+* The handler functions on views ``.get() .put() .post()`` etc, no longer have the ``content`` and ``auth`` args.
+ Use ``self.CONTENT`` inside a view to access the deserialized, validated content.
+ Use ``self.user`` inside a view to access the authenticated user.
+
+* ``allowed_methods`` and ``anon_allowed_methods`` are now defunct. if a method is defined, it's available.
+ The ``permissions`` attribute on a ``View`` is now used to provide generic permissions checking.
+ Use permission classes such as ``FullAnonAccess``, ``IsAuthenticated`` or ``IsUserOrIsAnonReadOnly`` to set the permissions.
+
+* The ``authenticators`` class becomes ``authentication``. Class names change to ``Authentication``.
+
+* The ``emitters`` class becomes ``renderers``. Class names change to ``Renderers``.
+
+* ``ResponseException`` becomes ``ErrorResponse``.
+
+* The mixin classes have been nicely refactored, the basic mixins are now ``RequestMixin``, ``ResponseMixin``, ``AuthMixin``, and ``ResourceMixin``
+ You can reuse these mixin classes individually without using the ``View`` class.
+
+## 0.1.1
+
+* Final build before pulling in all the refactoring changes for 0.2, in case anyone needs to hang on to 0.1.
+
+## 0.1.0
+
+* Initial release.
+
diff --git a/docs/tutorial/6-resource-orientated-projects.md b/docs/tutorial/6-resource-orientated-projects.md
index 4282c25d..0d0cfac5 100644
--- a/docs/tutorial/6-resource-orientated-projects.md
+++ b/docs/tutorial/6-resource-orientated-projects.md
@@ -1,3 +1,7 @@
+In REST framework Resources classes are just View classes that don't have any handler methods bound to them. This allows us to seperate out the behaviour of the classes from how that behaviour should be bound to a set of URLs.
+
+For instance, given our serializers
+
serializers.py
class BlogPostSerializer(URLModelSerializer):
@@ -8,21 +12,44 @@ serializers.py
class Meta:
model = Comment
+We can re-write our 4 sets of views into something more compact...
+
resources.py
class BlogPostResource(ModelResource):
serializer_class = BlogPostSerializer
model = BlogPost
- permissions = [AdminOrAnonReadonly()]
- throttles = [AnonThrottle(rate='5/min')]
+ permissions_classes = (permissions.IsAuthenticatedOrReadOnly,)
+ throttle_classes = (throttles.UserRateThrottle,)
class CommentResource(ModelResource):
serializer_class = CommentSerializer
model = Comment
- permissions = [AdminOrAnonReadonly()]
- throttles = [AnonThrottle(rate='5/min')]
+ permissions_classes = (permissions.IsAuthenticatedOrReadOnly,)
+ throttle_classes = (throttles.UserRateThrottle,)
+
+The handler methods only get bound to the actions when we define the URLConf. Here's our urls.py:
+
+ comment_root = CommentResource.as_view(actions={
+ 'get': 'list',
+ 'post': 'create'
+ })
+ comment_instance = CommentInstance.as_view(actions={
+ 'get': 'retrieve',
+ 'put': 'update',
+ 'delete': 'destroy'
+ })
+ ... # And for blog post
+
+ urlpatterns = patterns('blogpost.views',
+ url(r'^$', comment_root),
+ url(r'^(?P[0-9]+)$', comment_instance)
+ ... # And for blog post
+ )
+
+## Using Routers
-Now that we're using Resources rather than Views, we don't need to design the urlconf ourselves. The conventions for wiring up resources into views and urls are handled automatically. All we need to do is register the appropriate resources with a router, and let it do the rest. Here's our re-wired `urls.py` file.
+Right now that hasn't really saved us a lot of code. However, now that we're using Resources rather than Views, we actually don't need to design the urlconf ourselves. The conventions for wiring up resources into views and urls can be handled automatically, using `Router` classes. All we need to do is register the appropriate resources with a router, and let it do the rest. Here's our re-wired `urls.py` file.
from blog import resources
from djangorestframework.routers import DefaultRouter
--
cgit v1.2.3
From a5213d4023df344d1bc696483cd8db3a192f2b7a Mon Sep 17 00:00:00 2001
From: Tom Christie
Date: Fri, 14 Sep 2012 13:24:13 +0100
Subject: Drop urlobject2
---
docs/index.md | 1 -
1 file changed, 1 deletion(-)
(limited to 'docs')
diff --git a/docs/index.md b/docs/index.md
index c2035a19..2376d38e 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -17,7 +17,6 @@ REST framework requires the following:
* Python (2.6, 2.7)
* Django (1.3, 1.4, 1.5)
-* [URLObject][urlobject] (2.0.0+)
The following packages are optional:
--
cgit v1.2.3
From a96211d3d1ba246512af5e32c31726a666c467ac Mon Sep 17 00:00:00 2001
From: Tom Christie
Date: Sun, 16 Sep 2012 21:48:55 +0100
Subject: Simplify negotiation. Drop MSIE hacks. Etc.
---
docs/api-guide/content-negotiation.md | 2 ++
docs/topics/rest-hypermedia-hateoas.md | 52 ++++++++++++++++++++++++++++++++++
2 files changed, 54 insertions(+)
create mode 100644 docs/topics/rest-hypermedia-hateoas.md
(limited to 'docs')
diff --git a/docs/api-guide/content-negotiation.md b/docs/api-guide/content-negotiation.md
index 01895a4b..ad98de3b 100644
--- a/docs/api-guide/content-negotiation.md
+++ b/docs/api-guide/content-negotiation.md
@@ -1,3 +1,5 @@
+
+
# Content negotiation
> HTTP has provisions for several mechanisms for "content negotiation" - the process of selecting the best representation for a given response when there are multiple representations available.
diff --git a/docs/topics/rest-hypermedia-hateoas.md b/docs/topics/rest-hypermedia-hateoas.md
new file mode 100644
index 00000000..2bca2ab8
--- /dev/null
+++ b/docs/topics/rest-hypermedia-hateoas.md
@@ -0,0 +1,52 @@
+> You keep using that word "REST". I do not think it means what you think it means.
+>
+> — Mike Amundsen, [talking at REST fest 2012][cite].
+
+# REST, Hypermedia & HATEOAS
+
+First off, the disclaimer. The name "Django REST framework" was choosen with a view to making sure the project would be easily found by developers. Throughout the documentation we try to use the more simple and technically correct terminology of "Web APIs".
+
+If you are serious about designing a Hypermedia APIs, you should look to resources outside of this documentation to help inform your design choices.
+
+The following fall into the "required reading" category.
+
+* Fielding's dissertation - [Architectural Styles and
+the Design of Network-based Software Architectures][dissertation].
+* Fielding's "[REST APIs must be hypertext-driven][hypertext-driven]" blog post.
+* Leonard Richardson & Sam Ruby's [RESTful Web Services][restful-web-services].
+* Mike Amundsen's [Building Hypermedia APIs with HTML5 and Node][building-hypermedia-apis].
+* Steve Klabnik's [Designing Hypermedia APIs][designing-hypermedia-apis].
+* The [Richardson Maturity Model][maturitymodel].
+
+For a more thorough background, check out Klabnik's [Hypermedia API reading list][readinglist].
+
+# Building Hypermedia APIs with REST framework
+
+REST framework is an agnositic Web API toolkit. It does help guide you towards building well-connected APIs, and makes it easy to design appropriate media types, but it does not strictly enforce any particular design style.
+
+### What REST framework *does* provide.
+
+It is self evident that REST framework makes it possible to build Hypermedia APIs. The browseable API that it offers is built on HTML - the hypermedia language of the web.
+
+REST framework also includes [serialization] and [parser]/[renderer] components that make it easy to build appropriate media types, [hyperlinked relations][fields] for building well-connected systems, and great support for [content negotiation][conneg].
+
+### What REST framework *doesn't* provide.
+
+What REST framework doesn't do is give you is machine readable hypermedia formats such as [Collection+JSON][collection] by default, or the ability to auto-magically create HATEOAS style APIs. Doing so would involve making opinionated choices about API design that should really remain outside of the framework's scope.
+
+[cite]: http://vimeo.com/channels/restfest/page:2
+[dissertation]: http://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm
+[hypertext-driven]: http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven
+[restful-web-services]:
+[building-hypermedia-apis]: …
+[designing-hypermedia-apis]: http://designinghypermediaapis.com/
+[restisover]: http://blog.steveklabnik.com/posts/2012-02-23-rest-is-over
+[readinglist]: http://blog.steveklabnik.com/posts/2012-02-27-hypermedia-api-reading-list
+[maturitymodel]: http://martinfowler.com/articles/richardsonMaturityModel.html
+
+[collection]: http://www.amundsen.com/media-types/collection/
+[serialization]: ../api-guide/serializers.md
+[parser]: ../api-guide/parsers.md
+[renderer]: ../api-guide/renderers.md
+[fields]: ../api-guide/fields.md
+[conneg]: ../api-guide/content-negotiation.md
\ No newline at end of file
--
cgit v1.2.3
From 43c2a15f9d9423fdd3211684e18efeacd7534d3f Mon Sep 17 00:00:00 2001
From: Alec Perkins
Date: Mon, 17 Sep 2012 10:01:44 -0400
Subject: Prevent the touchstart event propagation on the dropdown menus in the
navbar.
This allows the dropdowns to be used on a touch device.---
docs/template.html | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
(limited to 'docs')
diff --git a/docs/template.html b/docs/template.html
index 127978d2..4ac94f40 100644
--- a/docs/template.html
+++ b/docs/template.html
@@ -118,7 +118,7 @@
if (location.hash) shiftWindow();
window.addEventListener("hashchange", shiftWindow);
- $('.dropdown-menu').click(function(event) {
+ $('.dropdown-menu').on('click touchstart', function(event) {
event.stopPropagation();
});
--
cgit v1.2.3
From 308677037f1b1f2edbd2527beac8505033c98bdc Mon Sep 17 00:00:00 2001
From: Tom Christie
Date: Mon, 17 Sep 2012 20:19:45 +0100
Subject: Tweak docs, fix .error_data -> .errors
---
docs/topics/rest-hypermedia-hateoas.md | 6 +++---
docs/tutorial/1-serialization.md | 4 ++--
docs/tutorial/2-requests-and-responses.md | 4 ++--
docs/tutorial/3-class-based-views.md | 29 +++++++++++++++--------------
4 files changed, 22 insertions(+), 21 deletions(-)
(limited to 'docs')
diff --git a/docs/topics/rest-hypermedia-hateoas.md b/docs/topics/rest-hypermedia-hateoas.md
index 2bca2ab8..46a4c9d7 100644
--- a/docs/topics/rest-hypermedia-hateoas.md
+++ b/docs/topics/rest-hypermedia-hateoas.md
@@ -1,8 +1,8 @@
+# REST, Hypermedia & HATEOAS
+
> You keep using that word "REST". I do not think it means what you think it means.
>
-> — Mike Amundsen, [talking at REST fest 2012][cite].
-
-# REST, Hypermedia & HATEOAS
+> — Mike Amundsen, [REST fest 2012 keynote][cite].
First off, the disclaimer. The name "Django REST framework" was choosen with a view to making sure the project would be easily found by developers. Throughout the documentation we try to use the more simple and technically correct terminology of "Web APIs".
diff --git a/docs/tutorial/1-serialization.md b/docs/tutorial/1-serialization.md
index 610d8ed1..34990084 100644
--- a/docs/tutorial/1-serialization.md
+++ b/docs/tutorial/1-serialization.md
@@ -194,7 +194,7 @@ The root of our API is going to be a view that supports listing all the existing
comment.save()
return JSONResponse(serializer.data, status=201)
else:
- return JSONResponse(serializer.error_data, status=400)
+ return JSONResponse(serializer.errors, status=400)
We'll also need a view which corrosponds to an individual comment, and can be used to retrieve, update or delete the comment.
@@ -219,7 +219,7 @@ We'll also need a view which corrosponds to an individual comment, and can be us
comment.save()
return JSONResponse(serializer.data)
else:
- return JSONResponse(serializer.error_data, status=400)
+ return JSONResponse(serializer.errors, status=400)
elif request.method == 'DELETE':
comment.delete()
diff --git a/docs/tutorial/2-requests-and-responses.md b/docs/tutorial/2-requests-and-responses.md
index 2c11d5ef..ffc5f269 100644
--- a/docs/tutorial/2-requests-and-responses.md
+++ b/docs/tutorial/2-requests-and-responses.md
@@ -61,7 +61,7 @@ We don't need our `JSONResponse` class anymore, so go ahead and delete that. On
comment.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
else:
- return Response(serializer.error_data, status=status.HTTP_400_BAD_REQUEST)
+ return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
Our instance view is an improvement over the previous example. It's a little more concise, and the code now feels very similar to if we were working with the Forms API. We're also using named status codes, which makes the response meanings more obvious.
@@ -87,7 +87,7 @@ Our instance view is an improvement over the previous example. It's a little mo
comment.save()
return Response(serializer.data)
else:
- return Response(serializer.error_data, status=status.HTTP_400_BAD_REQUEST)
+ return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
elif request.method == 'DELETE':
comment.delete()
diff --git a/docs/tutorial/3-class-based-views.md b/docs/tutorial/3-class-based-views.md
index 24785179..3c8f1207 100644
--- a/docs/tutorial/3-class-based-views.md
+++ b/docs/tutorial/3-class-based-views.md
@@ -31,8 +31,6 @@ We'll start by rewriting the root view as a class based view. All this involves
return Response(serializer.serialized, status=status.HTTP_201_CREATED)
return Response(serializer.serialized_errors, status=status.HTTP_400_BAD_REQUEST)
- comment_root = CommentRoot.as_view()
-
So far, so good. It looks pretty similar to the previous case, but we've got better seperation between the different HTTP methods. We'll also need to update the instance view.
class CommentInstance(APIView):
@@ -58,16 +56,28 @@ So far, so good. It looks pretty similar to the previous case, but we've got be
comment = serializer.deserialized
comment.save()
return Response(serializer.data)
- return Response(serializer.error_data, status=status.HTTP_400_BAD_REQUEST)
+ return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def delete(self, request, pk, format=None):
comment = self.get_object(pk)
comment.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
- comment_instance = CommentInstance.as_view()
-
That's looking good. Again, it's still pretty similar to the function based view right now.
+
+We'll also need to refactor our URLconf slightly now we're using class based views.
+
+ from django.conf.urls import patterns, url
+ from djangorestframework.urlpatterns import format_suffix_patterns
+ from blogpost import views
+
+ urlpatterns = patterns('',
+ url(r'^$', views.CommentRoot.as_view()),
+ url(r'^(?P[0-9]+)$', views.CommentInstance.as_view())
+ )
+
+ urlpatterns = format_suffix_patterns(urlpatterns)
+
Okay, we're done. If you run the development server everything should be working just as before.
## Using mixins
@@ -95,8 +105,6 @@ Let's take a look at how we can compose our views by using the mixin classes.
def post(self, request, *args, **kwargs):
return self.create(request, *args, **kwargs)
- comment_root = CommentRoot.as_view()
-
We'll take a moment to examine exactly what's happening here - We're building our view using `MultipleObjectBaseView`, and adding in `ListModelMixin` and `CreateModelMixin`.
The base class provides the core functionality, and the mixin classes provide the `.list()` and `.create()` actions. We're then explictly binding the `get` and `post` methods to the appropriate actions. Simple enough stuff so far.
@@ -117,8 +125,6 @@ The base class provides the core functionality, and the mixin classes provide th
def delete(self, request, *args, **kwargs):
return self.destroy(request, *args, **kwargs)
- comment_instance = CommentInstance.as_view()
-
Pretty similar. This time we're using the `SingleObjectBaseView` class to provide the core functionality, and adding in mixins to provide the `.retrieve()`, `.update()` and `.destroy()` actions.
## Using generic class based views
@@ -134,16 +140,11 @@ Using the mixin classes we've rewritten the views to use slightly less code than
model = Comment
serializer_class = CommentSerializer
- comment_root = CommentRoot.as_view()
-
class CommentInstance(generics.InstanceAPIView):
model = Comment
serializer_class = CommentSerializer
- comment_instance = CommentInstance.as_view()
-
-
Wow, that's pretty concise. We've got a huge amount for free, and our code looks like good, clean, idomatic Django.
Next we'll move onto [part 4 of the tutorial][2], where we'll take a look at how we can customize the behavior of our views to support a range of authentication, permissions, throttling and other aspects.
--
cgit v1.2.3
From 575630d7c34b8ee23dad379c4bbd01eba477e4a2 Mon Sep 17 00:00:00 2001
From: Tom Christie
Date: Wed, 19 Sep 2012 13:02:10 +0100
Subject: Use named links in tutorial docs
---
docs/tutorial/2-requests-and-responses.md | 16 +++++++--------
docs/tutorial/3-class-based-views.md | 8 ++++----
.../4-authentication-permissions-and-throttling.md | 6 ++++--
.../5-relationships-and-hyperlinked-apis.md | 6 ++++--
docs/tutorial/6-resource-orientated-projects.md | 24 +++++++++++-----------
5 files changed, 32 insertions(+), 28 deletions(-)
(limited to 'docs')
diff --git a/docs/tutorial/2-requests-and-responses.md b/docs/tutorial/2-requests-and-responses.md
index ffc5f269..906f11d0 100644
--- a/docs/tutorial/2-requests-and-responses.md
+++ b/docs/tutorial/2-requests-and-responses.md
@@ -125,11 +125,11 @@ We don't necessarily need to add these extra url patterns in, but it gives us a
## How's it looking?
-Go ahead and test the API from the command line, as we did in [tutorial part 1][2]. Everything is working pretty similarly, although we've got some nicer error handling if we send invalid requests.
+Go ahead and test the API from the command line, as we did in [tutorial part 1][tut-1]. Everything is working pretty similarly, although we've got some nicer error handling if we send invalid requests.
**TODO: Describe using accept headers, content-type headers, and format suffixed URLs**
-Now go and open the API in a web browser, by visiting [http://127.0.0.1:8000/][3]."
+Now go and open the API in a web browser, by visiting [http://127.0.0.1:8000/][devserver]."
**Note: Right now the Browseable API only works with the CBV's. Need to fix that.**
@@ -137,15 +137,15 @@ Now go and open the API in a web browser, by visiting [http://127.0.0.1:8000/][3
Because the API chooses a return format based on what the client asks for, it will, by default, return an HTML-formatted representation of the resource when that resource is requested by a browser. This allows for the API to be easily browsable and usable by humans.
-See the [browsable api][4] topic for more information about the browsable API feature and how to customize it.
+See the [browsable api][browseable-api] topic for more information about the browsable API feature and how to customize it.
## What's next?
-In [tutorial part 3][4], we'll start using class based views, and see how generic views reduce the amount of code we need to write.
+In [tutorial part 3][tut-3], we'll start using class based views, and see how generic views reduce the amount of code we need to write.
[json-url]: http://example.com/api/items/4.json
-[2]: 1-serialization.md
-[3]: http://127.0.0.1:8000/
-[4]: ../topics/browsable-api.md
-[5]: 3-class-based-views.md
\ No newline at end of file
+[devserver]: http://127.0.0.1:8000/
+[browseable-api]: ../topics/browsable-api.md
+[tut-1]: 1-serialization.md
+[tut-3]: 3-class-based-views.md
\ No newline at end of file
diff --git a/docs/tutorial/3-class-based-views.md b/docs/tutorial/3-class-based-views.md
index 3c8f1207..79866f0d 100644
--- a/docs/tutorial/3-class-based-views.md
+++ b/docs/tutorial/3-class-based-views.md
@@ -1,6 +1,6 @@
# Tutorial 3: Class Based Views
-We can also write our API views using class based views, rather than function based views. As we'll see this is a powerful pattern that allows us to reuse common functionality, and helps us keep our code [DRY][1].
+We can also write our API views using class based views, rather than function based views. As we'll see this is a powerful pattern that allows us to reuse common functionality, and helps us keep our code [DRY][dry].
## Rewriting our API using class based views
@@ -147,7 +147,7 @@ Using the mixin classes we've rewritten the views to use slightly less code than
Wow, that's pretty concise. We've got a huge amount for free, and our code looks like good, clean, idomatic Django.
-Next we'll move onto [part 4 of the tutorial][2], where we'll take a look at how we can customize the behavior of our views to support a range of authentication, permissions, throttling and other aspects.
+Next we'll move onto [part 4 of the tutorial][tut-4], where we'll take a look at how we can customize the behavior of our views to support a range of authentication, permissions, throttling and other aspects.
-[1]: http://en.wikipedia.org/wiki/Don't_repeat_yourself
-[2]: 4-authentication-permissions-and-throttling.md
+[dry]: http://en.wikipedia.org/wiki/Don't_repeat_yourself
+[tut-4]: 4-authentication-permissions-and-throttling.md
diff --git a/docs/tutorial/4-authentication-permissions-and-throttling.md b/docs/tutorial/4-authentication-permissions-and-throttling.md
index 5c37ae13..c8d7cbd3 100644
--- a/docs/tutorial/4-authentication-permissions-and-throttling.md
+++ b/docs/tutorial/4-authentication-permissions-and-throttling.md
@@ -1,3 +1,5 @@
-[part 5][5]
+# Tutorial 4: Authentication & Permissions
-[5]: 5-relationships-and-hyperlinked-apis.md
\ No newline at end of file
+Nothing to see here. Onwards to [part 5][tut-5].
+
+[tut-5]: 5-relationships-and-hyperlinked-apis.md
\ No newline at end of file
diff --git a/docs/tutorial/5-relationships-and-hyperlinked-apis.md b/docs/tutorial/5-relationships-and-hyperlinked-apis.md
index 3d9598d7..a76f81e8 100644
--- a/docs/tutorial/5-relationships-and-hyperlinked-apis.md
+++ b/docs/tutorial/5-relationships-and-hyperlinked-apis.md
@@ -1,9 +1,11 @@
+# Tutorial 5 - Relationships & Hyperlinked APIs
+
**TODO**
* Create BlogPost model
* Demonstrate nested relationships
* Demonstrate and describe hyperlinked relationships
-[part 6][1]
+Onwards to [part 6][tut-6].
-[1]: 6-resource-orientated-projects.md
+[tut-6]: 6-resource-orientated-projects.md
diff --git a/docs/tutorial/6-resource-orientated-projects.md b/docs/tutorial/6-resource-orientated-projects.md
index 0d0cfac5..7da409fb 100644
--- a/docs/tutorial/6-resource-orientated-projects.md
+++ b/docs/tutorial/6-resource-orientated-projects.md
@@ -1,18 +1,15 @@
-In REST framework Resources classes are just View classes that don't have any handler methods bound to them. This allows us to seperate out the behaviour of the classes from how that behaviour should be bound to a set of URLs.
+# Tutorial 6 - Resources
-For instance, given our serializers
+Resource classes are just View classes that don't have any handler methods bound to them. The actions on a resource are defined,
-serializers.py
+This allows us to:
- class BlogPostSerializer(URLModelSerializer):
- class Meta:
- model = BlogPost
+* Encapsulate common behaviour accross a class of views, in a single Resource class.
+* Seperate out the actions of a Resource from the specfics of how those actions should be bound to a particular set of URLs.
- class CommentSerializer(URLModelSerializer):
- class Meta:
- model = Comment
+## Refactoring to use Resources, not Views
-We can re-write our 4 sets of views into something more compact...
+For instance, we can re-write our 4 sets of views into something more compact...
resources.py
@@ -28,6 +25,7 @@ resources.py
permissions_classes = (permissions.IsAuthenticatedOrReadOnly,)
throttle_classes = (throttles.UserRateThrottle,)
+## Binding Resources to URLs explicitly
The handler methods only get bound to the actions when we define the URLConf. Here's our urls.py:
comment_root = CommentResource.as_view(actions={
@@ -71,6 +69,8 @@ We've reached the end of our tutorial. If you want to get more involved in the
* Contribute on GitHub by reviewing issues, and submitting issues or pull requests.
* Join the REST framework group, and help build the community.
-* Follow me [on Twitter](https://twitter.com/_tomchristie) and say hi.
+* Follow me [on Twitter][twitter] and say hi.
-Now go build something great.
\ No newline at end of file
+**Now go build some awesome things.**
+
+[twitter]: https://twitter.com/_tomchristie
\ No newline at end of file
--
cgit v1.2.3
From db13401af0d8c84007b8fcfafda560bef964935b Mon Sep 17 00:00:00 2001
From: Tom Christie
Date: Wed, 19 Sep 2012 17:06:43 +0100
Subject: Added @phobologic. Thanks\!
---
docs/topics/credits.md | 2 ++
1 file changed, 2 insertions(+)
(limited to 'docs')
diff --git a/docs/topics/credits.md b/docs/topics/credits.md
index c20f5246..e54fd4bf 100644
--- a/docs/topics/credits.md
+++ b/docs/topics/credits.md
@@ -40,6 +40,7 @@ The following people have helped make REST framework great.
* Can Yavuz - [tschan]
* Shawn Lewis - [shawnlewis]
* Alec Perkins - [alecperkins]
+* Michael Barrett - [phobologic]
Many thanks to everyone who's contributed to the project.
@@ -102,3 +103,4 @@ To contact the author directly:
[tschan]: https://github.com/tschan
[shawnlewis]: https://github.com/shawnlewis
[alecperkins]: https://github.com/alecperkins
+[phobologic]: https://github.com/phobologic
--
cgit v1.2.3
From 4b691c402707775c3048a90531024f3bc5be6f91 Mon Sep 17 00:00:00 2001
From: Tom Christie
Date: Thu, 20 Sep 2012 13:06:27 +0100
Subject: Change package name: djangorestframework -> rest_framework
---
docs/api-guide/authentication.md | 14 ++++++-------
docs/api-guide/permissions.md | 6 +++---
docs/api-guide/requests.md | 6 +++---
docs/api-guide/reverse.md | 6 +++---
docs/api-guide/settings.md | 28 ++++++++++++-------------
docs/api-guide/status-codes.md | 2 +-
docs/api-guide/throttling.md | 14 ++++++-------
docs/index.md | 12 ++++++-----
docs/topics/browsable-api.md | 4 ++--
docs/tutorial/1-serialization.md | 16 +++++++-------
docs/tutorial/2-requests-and-responses.md | 10 ++++-----
docs/tutorial/3-class-based-views.md | 14 ++++++-------
docs/tutorial/6-resource-orientated-projects.md | 4 ++--
13 files changed, 69 insertions(+), 67 deletions(-)
(limited to 'docs')
diff --git a/docs/api-guide/authentication.md b/docs/api-guide/authentication.md
index 79950946..f24c6a81 100644
--- a/docs/api-guide/authentication.md
+++ b/docs/api-guide/authentication.md
@@ -28,10 +28,10 @@ The value of `request.user` and `request.auth` for unauthenticated requests can
The default authentication policy may be set globally, using the `DEFAULT_AUTHENTICATION` setting. For example.
- API_SETTINGS = {
+ REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION': (
- 'djangorestframework.authentication.UserBasicAuthentication',
- 'djangorestframework.authentication.SessionAuthentication',
+ 'rest_framework.authentication.UserBasicAuthentication',
+ 'rest_framework.authentication.SessionAuthentication',
)
}
@@ -75,11 +75,11 @@ If successfully authenticated, `BasicAuthentication` provides the following cred
This policy uses a simple token-based HTTP Authentication scheme. Token authentication is appropriate for client-server setups, such as native desktop and mobile clients.
-To use the `TokenAuthentication` policy, include `djangorestframework.authtoken` in your `INSTALLED_APPS` setting.
+To use the `TokenAuthentication` policy, include `rest_framework.authtoken` in your `INSTALLED_APPS` setting.
You'll also need to create tokens for your users.
- from djangorestframework.authtoken.models import Token
+ from rest_framework.authtoken.models import Token
token = Token.objects.create(user=...)
print token.key
@@ -91,7 +91,7 @@ For clients to authenticate, the token key should be included in the `Authorizat
If successfully authenticated, `TokenAuthentication` provides the following credentials.
* `request.user` will be a `django.contrib.auth.models.User` instance.
-* `request.auth` will be a `djangorestframework.tokenauth.models.BasicToken` instance.
+* `request.auth` will be a `rest_framework.tokenauth.models.BasicToken` instance.
**Note:** If you use `TokenAuthentication` in production you must ensure that your API is only available over `https` only.
@@ -102,7 +102,7 @@ This policy uses the [OAuth 2.0][oauth] protocol to authenticate requests. OAut
If successfully authenticated, `OAuthAuthentication` provides the following credentials.
* `request.user` will be a `django.contrib.auth.models.User` instance.
-* `request.auth` will be a `djangorestframework.models.OAuthToken` instance.
+* `request.auth` will be a `rest_framework.models.OAuthToken` instance.
## SessionAuthentication
diff --git a/docs/api-guide/permissions.md b/docs/api-guide/permissions.md
index fafef305..e0ceb1ea 100644
--- a/docs/api-guide/permissions.md
+++ b/docs/api-guide/permissions.md
@@ -27,9 +27,9 @@ Object level permissions are run by REST framework's generic views when `.get_ob
The default permission policy may be set globally, using the `DEFAULT_PERMISSIONS` setting. For example.
- API_SETTINGS = {
+ REST_FRAMEWORK = {
'DEFAULT_PERMISSIONS': (
- 'djangorestframework.permissions.IsAuthenticated',
+ 'rest_framework.permissions.IsAuthenticated',
)
}
@@ -97,4 +97,4 @@ The method should return `True` if the request should be granted access, and `Fa
[authentication]: authentication.md
[throttling]: throttling.md
[contribauth]: https://docs.djangoproject.com/en/1.0/topics/auth/#permissions
-[guardian]: https://github.com/lukaszb/django-guardian
\ No newline at end of file
+[guardian]: https://github.com/lukaszb/django-guardian
diff --git a/docs/api-guide/requests.md b/docs/api-guide/requests.md
index 6746bb20..b223da80 100644
--- a/docs/api-guide/requests.md
+++ b/docs/api-guide/requests.md
@@ -49,7 +49,7 @@ This allows you to support file uploads from multiple content-types. For exampl
`request.parsers` may no longer be altered once `request.DATA`, `request.FILES` or `request.POST` have been accessed.
-If you're using the `djangorestframework.views.View` class... **[TODO]**
+If you're using the `rest_framework.views.View` class... **[TODO]**
## .stream
@@ -63,6 +63,6 @@ You will not typically need to access `request.stream`, unless you're writing a
`request.authentication` may no longer be altered once `request.user` or `request.auth` have been accessed.
-If you're using the `djangorestframework.views.View` class... **[TODO]**
+If you're using the `rest_framework.views.View` class... **[TODO]**
-[cite]: https://groups.google.com/d/topic/django-developers/dxI4qVzrBY4/discussion
\ No newline at end of file
+[cite]: https://groups.google.com/d/topic/django-developers/dxI4qVzrBY4/discussion
diff --git a/docs/api-guide/reverse.md b/docs/api-guide/reverse.md
index f3cb0c64..3fa654c0 100644
--- a/docs/api-guide/reverse.md
+++ b/docs/api-guide/reverse.md
@@ -23,8 +23,8 @@ There's no requirement for you to use them, but if you do then the self-describi
Has the same behavior as [`django.core.urlresolvers.reverse`][reverse], except that it returns a fully qualified URL, using the request to determine the host and port.
- from djangorestframework.utils import reverse
- from djangorestframework.views import APIView
+ from rest_framework.utils import reverse
+ from rest_framework.views import APIView
class MyView(APIView):
def get(self, request):
@@ -40,4 +40,4 @@ Has the same behavior as [`django.core.urlresolvers.reverse_lazy`][reverse-lazy]
[cite]: http://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm#sec_5_1_5
[reverse]: https://docs.djangoproject.com/en/dev/topics/http/urls/#reverse
-[reverse-lazy]: https://docs.djangoproject.com/en/dev/topics/http/urls/#reverse-lazy
\ No newline at end of file
+[reverse-lazy]: https://docs.djangoproject.com/en/dev/topics/http/urls/#reverse-lazy
diff --git a/docs/api-guide/settings.md b/docs/api-guide/settings.md
index 2513928c..0f66e85e 100644
--- a/docs/api-guide/settings.md
+++ b/docs/api-guide/settings.md
@@ -6,16 +6,16 @@
>
> — [The Zen of Python][cite]
-Configuration for REST framework is all namespaced inside a single Django setting, named `API_SETTINGS`.
+Configuration for REST framework is all namespaced inside a single Django setting, named `REST_FRAMEWORK`.
For example your project's `settings.py` file might include something like this:
- API_SETTINGS = {
+ REST_FRAMEWORK = {
'DEFAULT_RENDERERS': (
- 'djangorestframework.renderers.YAMLRenderer',
+ 'rest_framework.renderers.YAMLRenderer',
)
'DEFAULT_PARSERS': (
- 'djangorestframework.parsers.YAMLParser',
+ 'rest_framework.parsers.YAMLParser',
)
}
@@ -24,7 +24,7 @@ For example your project's `settings.py` file might include something like this:
If you need to access the values of REST framework's API settings in your project,
you should use the `api_settings` object. For example.
- from djangorestframework.settings import api_settings
+ from rest_framework.settings import api_settings
print api_settings.DEFAULT_AUTHENTICATION
@@ -37,9 +37,9 @@ A list or tuple of renderer classes, that determines the default set of renderer
Default:
(
- 'djangorestframework.renderers.JSONRenderer',
- 'djangorestframework.renderers.DocumentingHTMLRenderer'
- 'djangorestframework.renderers.TemplateHTMLRenderer'
+ 'rest_framework.renderers.JSONRenderer',
+ 'rest_framework.renderers.DocumentingHTMLRenderer'
+ 'rest_framework.renderers.TemplateHTMLRenderer'
)
## DEFAULT_PARSERS
@@ -49,8 +49,8 @@ A list or tuple of parser classes, that determines the default set of parsers us
Default:
(
- 'djangorestframework.parsers.JSONParser',
- 'djangorestframework.parsers.FormParser'
+ 'rest_framework.parsers.JSONParser',
+ 'rest_framework.parsers.FormParser'
)
## DEFAULT_AUTHENTICATION
@@ -60,8 +60,8 @@ A list or tuple of authentication classes, that determines the default set of au
Default:
(
- 'djangorestframework.authentication.SessionAuthentication',
- 'djangorestframework.authentication.UserBasicAuthentication'
+ 'rest_framework.authentication.SessionAuthentication',
+ 'rest_framework.authentication.UserBasicAuthentication'
)
## DEFAULT_PERMISSIONS
@@ -80,13 +80,13 @@ Default: `()`
**TODO**
-Default: `djangorestframework.serializers.ModelSerializer`
+Default: `rest_framework.serializers.ModelSerializer`
## DEFAULT_PAGINATION_SERIALIZER
**TODO**
-Default: `djangorestframework.pagination.PaginationSerializer`
+Default: `rest_framework.pagination.PaginationSerializer`
## FORMAT_SUFFIX_KWARG
diff --git a/docs/api-guide/status-codes.md b/docs/api-guide/status-codes.md
index 6693c79f..401f45ce 100644
--- a/docs/api-guide/status-codes.md
+++ b/docs/api-guide/status-codes.md
@@ -8,7 +8,7 @@
Using bare status codes in your responses isn't recommended. REST framework includes a set of named constants that you can use to make more code more obvious and readable.
- from djangorestframework import status
+ from rest_framework import status
def empty_view(self):
content = {'please move along': 'nothing to see here'}
diff --git a/docs/api-guide/throttling.md b/docs/api-guide/throttling.md
index 10997801..7861e9ba 100644
--- a/docs/api-guide/throttling.md
+++ b/docs/api-guide/throttling.md
@@ -29,10 +29,10 @@ If any throttle check fails an `exceptions.Throttled` exception will be raised,
The default throttling policy may be set globally, using the `DEFAULT_THROTTLES` and `DEFAULT_THROTTLE_RATES` settings. For example.
- API_SETTINGS = {
+ REST_FRAMEWORK = {
'DEFAULT_THROTTLES': (
- 'djangorestframework.throttles.AnonThrottle',
- 'djangorestframework.throttles.UserThrottle',
+ 'rest_framework.throttles.AnonThrottle',
+ 'rest_framework.throttles.UserThrottle',
)
'DEFAULT_THROTTLE_RATES': {
'anon': '100/day',
@@ -95,7 +95,7 @@ For example, multiple user throttle rates could be implemented by using the foll
...and the following settings.
- API_SETTINGS = {
+ REST_FRAMEWORK = {
'DEFAULT_THROTTLES': (
'example.throttles.BurstRateThrottle',
'example.throttles.SustainedRateThrottle',
@@ -130,9 +130,9 @@ For example, given the following views...
...and the following settings.
- API_SETTINGS = {
+ REST_FRAMEWORK = {
'DEFAULT_THROTTLES': (
- 'djangorestframework.throttles.ScopedRateThrottle',
+ 'rest_framework.throttles.ScopedRateThrottle',
)
'DEFAULT_THROTTLE_RATES': {
'contacts': '1000/day',
@@ -148,4 +148,4 @@ To create a custom throttle, override `BaseThrottle` and implement `.allow_reque
Optionally you may also override the `.wait()` method. If implemented, `.wait()` should return a recomended number of seconds to wait before attempting the next request, or `None`. The `.wait()` method will only be called if `.check_throttle()` has previously returned `False`.
-[permissions]: permissions.md
\ No newline at end of file
+[permissions]: permissions.md
diff --git a/docs/index.md b/docs/index.md
index 2376d38e..e7db5dbc 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -40,20 +40,22 @@ Install using `pip`, including any optional packages you want...
pip install -r requirements.txt
pip install -r optionals.txt
-Add `djangorestframework` to your `INSTALLED_APPS`.
+Add `rest_framework` to your `INSTALLED_APPS`.
INSTALLED_APPS = (
...
- 'djangorestframework',
+ 'rest_framework',
)
If you're intending to use the browserable API you'll want to add REST framework's login and logout views. Add the following to your root `urls.py` file.
urlpatterns = patterns('',
...
- url(r'^api-auth/', include('djangorestframework.urls', namespace='djangorestframework'))
+ url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework'))
)
-
+
+Note that the base URL can be whatever you want, but you must include `rest_framework.urls` with the `rest_framework` namespace.
+
## Quickstart
**TODO**
@@ -110,7 +112,7 @@ Build the docs:
Run the tests:
- ./djangorestframework/runtests/runtests.py
+ ./rest_framework/runtests/runtests.py
## License
diff --git a/docs/topics/browsable-api.md b/docs/topics/browsable-api.md
index 6f8920bb..ed27752f 100644
--- a/docs/topics/browsable-api.md
+++ b/docs/topics/browsable-api.md
@@ -4,7 +4,7 @@ API may stand for Application *Programming* Interface, but humans have to be abl
## URLs
-If you include fully-qualified URLs in your resource output, they will be 'urlized' and made clickable for easy browsing by humans. The `djangorestframework` package includes a [`reverse`][drfreverse] helper for this purpose.
+If you include fully-qualified URLs in your resource output, they will be 'urlized' and made clickable for easy browsing by humans. The `rest_framework` package includes a [`reverse`][drfreverse] helper for this purpose.
## Formats
@@ -14,7 +14,7 @@ By default, the API will return the format specified by the headers, which in th
## Customizing
-To customize the look-and-feel, create a template called `api.html` and add it to your project, eg: `templates/djangorestframework/api.html`, that extends the `djangorestframework/base.html` template.
+To customize the look-and-feel, create a template called `api.html` and add it to your project, eg: `templates/rest_framework/api.html`, that extends the `rest_framework/base.html` template.
The included browsable API template is built with [Bootstrap (2.1.1)][bootstrap], making it easy to customize the look-and-feel.
diff --git a/docs/tutorial/1-serialization.md b/docs/tutorial/1-serialization.md
index 34990084..e3656bd0 100644
--- a/docs/tutorial/1-serialization.md
+++ b/docs/tutorial/1-serialization.md
@@ -45,11 +45,11 @@ The simplest way to get up and running will probably be to use an `sqlite3` data
}
}
-We'll also need to add our new `blog` app and the `djangorestframework` app to `INSTALLED_APPS`.
+We'll also need to add our new `blog` app and the `rest_framework` app to `INSTALLED_APPS`.
INSTALLED_APPS = (
...
- 'djangorestframework',
+ 'rest_framework',
'blog'
)
@@ -81,7 +81,7 @@ Don't forget to sync the database for the first time.
We're going to create a simple Web API that we can use to edit these comment objects with. The first thing we need is a way of serializing and deserializing the objects into representations such as `json`. We do this by declaring serializers, that work very similarly to Django's forms. Create a file in the project named `serializers.py` and add the following.
from blog import models
- from djangorestframework import serializers
+ from rest_framework import serializers
class CommentSerializer(serializers.Serializer):
@@ -114,8 +114,8 @@ Okay, once we've got a few imports out of the way, we'd better create a few comm
from blog.models import Comment
from blog.serializers import CommentSerializer
- from djangorestframework.renderers import JSONRenderer
- from djangorestframework.parsers import JSONParser
+ from rest_framework.renderers import JSONRenderer
+ from rest_framework.parsers import JSONParser
c1 = Comment(email='leila@example.com', content='nothing to say')
c2 = Comment(email='tom@example.com', content='foo bar')
@@ -159,8 +159,8 @@ Edit the `blog/views.py` file, and add the following.
from blog.models import Comment
from blog.serializers import CommentSerializer
- from djangorestframework.renderers import JSONRenderer
- from djangorestframework.parsers import JSONParser
+ from rest_framework.renderers import JSONRenderer
+ from rest_framework.parsers import JSONParser
from django.http import HttpResponse
@@ -251,4 +251,4 @@ Our API views don't do anything particularly special at the moment, beyond serve
We'll see how we can start to improve things in [part 2 of the tutorial][tut-2].
[virtualenv]: http://www.virtualenv.org/en/latest/index.html
-[tut-2]: 2-requests-and-responses.md
\ No newline at end of file
+[tut-2]: 2-requests-and-responses.md
diff --git a/docs/tutorial/2-requests-and-responses.md b/docs/tutorial/2-requests-and-responses.md
index 906f11d0..d889b1e0 100644
--- a/docs/tutorial/2-requests-and-responses.md
+++ b/docs/tutorial/2-requests-and-responses.md
@@ -40,9 +40,9 @@ We don't need our `JSONResponse` class anymore, so go ahead and delete that. On
from blog.models import Comment
from blog.serializers import CommentSerializer
- from djangorestframework import status
- from djangorestframework.decorators import api_view
- from djangorestframework.response import Response
+ from rest_framework import status
+ from rest_framework.decorators import api_view
+ from rest_framework.response import Response
@api_view(['GET', 'POST'])
def comment_root(request):
@@ -112,7 +112,7 @@ and
Now update the `urls.py` file slightly, to append a set of `format_suffix_patterns` in addition to the existing URLs.
from django.conf.urls import patterns, url
- from djangorestframework.urlpatterns import format_suffix_patterns
+ from rest_framework.urlpatterns import format_suffix_patterns
urlpatterns = patterns('blogpost.views',
url(r'^$', 'comment_root'),
@@ -148,4 +148,4 @@ In [tutorial part 3][tut-3], we'll start using class based views, and see how ge
[devserver]: http://127.0.0.1:8000/
[browseable-api]: ../topics/browsable-api.md
[tut-1]: 1-serialization.md
-[tut-3]: 3-class-based-views.md
\ No newline at end of file
+[tut-3]: 3-class-based-views.md
diff --git a/docs/tutorial/3-class-based-views.md b/docs/tutorial/3-class-based-views.md
index 79866f0d..8db29308 100644
--- a/docs/tutorial/3-class-based-views.md
+++ b/docs/tutorial/3-class-based-views.md
@@ -9,9 +9,9 @@ We'll start by rewriting the root view as a class based view. All this involves
from blog.models import Comment
from blog.serializers import CommentSerializer
from django.http import Http404
- from djangorestframework.views import APIView
- from djangorestframework.response import Response
- from djangorestframework import status
+ from rest_framework.views import APIView
+ from rest_framework.response import Response
+ from rest_framework import status
class CommentRoot(APIView):
@@ -68,7 +68,7 @@ That's looking good. Again, it's still pretty similar to the function based vie
We'll also need to refactor our URLconf slightly now we're using class based views.
from django.conf.urls import patterns, url
- from djangorestframework.urlpatterns import format_suffix_patterns
+ from rest_framework.urlpatterns import format_suffix_patterns
from blogpost import views
urlpatterns = patterns('',
@@ -90,8 +90,8 @@ Let's take a look at how we can compose our views by using the mixin classes.
from blog.models import Comment
from blog.serializers import CommentSerializer
- from djangorestframework import mixins
- from djangorestframework import generics
+ from rest_framework import mixins
+ from rest_framework import generics
class CommentRoot(mixins.ListModelMixin,
mixins.CreateModelMixin,
@@ -133,7 +133,7 @@ Using the mixin classes we've rewritten the views to use slightly less code than
from blog.models import Comment
from blog.serializers import CommentSerializer
- from djangorestframework import generics
+ from rest_framework import generics
class CommentRoot(generics.RootAPIView):
diff --git a/docs/tutorial/6-resource-orientated-projects.md b/docs/tutorial/6-resource-orientated-projects.md
index 7da409fb..3c3e7fed 100644
--- a/docs/tutorial/6-resource-orientated-projects.md
+++ b/docs/tutorial/6-resource-orientated-projects.md
@@ -50,7 +50,7 @@ The handler methods only get bound to the actions when we define the URLConf. He
Right now that hasn't really saved us a lot of code. However, now that we're using Resources rather than Views, we actually don't need to design the urlconf ourselves. The conventions for wiring up resources into views and urls can be handled automatically, using `Router` classes. All we need to do is register the appropriate resources with a router, and let it do the rest. Here's our re-wired `urls.py` file.
from blog import resources
- from djangorestframework.routers import DefaultRouter
+ from rest_framework.routers import DefaultRouter
router = DefaultRouter()
router.register(resources.BlogPostResource)
@@ -73,4 +73,4 @@ We've reached the end of our tutorial. If you want to get more involved in the
**Now go build some awesome things.**
-[twitter]: https://twitter.com/_tomchristie
\ No newline at end of file
+[twitter]: https://twitter.com/_tomchristie
--
cgit v1.2.3
From 921c5840aa64c184bcfa6cc2344d0fdca406548b Mon Sep 17 00:00:00 2001
From: Tom Christie
Date: Tue, 25 Sep 2012 12:21:35 +0100
Subject: Fix incorrect bit of tutorial
---
docs/tutorial/3-class-based-views.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
(limited to 'docs')
diff --git a/docs/tutorial/3-class-based-views.md b/docs/tutorial/3-class-based-views.md
index 8db29308..25d5773f 100644
--- a/docs/tutorial/3-class-based-views.md
+++ b/docs/tutorial/3-class-based-views.md
@@ -53,7 +53,7 @@ So far, so good. It looks pretty similar to the previous case, but we've got be
comment = self.get_object(pk)
serializer = CommentSerializer(request.DATA, instance=comment)
if serializer.is_valid():
- comment = serializer.deserialized
+ comment = serializer.object
comment.save()
return Response(serializer.data)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
--
cgit v1.2.3
From 4fb57d28e60c02593f14ba7cdebed4e478371512 Mon Sep 17 00:00:00 2001
From: Tom Christie
Date: Tue, 25 Sep 2012 12:27:46 +0100
Subject: Add csrf note
---
docs/tutorial/1-serialization.md | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
(limited to 'docs')
diff --git a/docs/tutorial/1-serialization.md b/docs/tutorial/1-serialization.md
index e3656bd0..04942834 100644
--- a/docs/tutorial/1-serialization.md
+++ b/docs/tutorial/1-serialization.md
@@ -159,9 +159,10 @@ Edit the `blog/views.py` file, and add the following.
from blog.models import Comment
from blog.serializers import CommentSerializer
+ from django.http import HttpResponse
+ from django.views.decorators.csrf import csrf_exempt
from rest_framework.renderers import JSONRenderer
from rest_framework.parsers import JSONParser
- from django.http import HttpResponse
class JSONResponse(HttpResponse):
@@ -177,6 +178,7 @@ Edit the `blog/views.py` file, and add the following.
The root of our API is going to be a view that supports listing all the existing comments, or creating a new comment.
+ @csrf_exempt
def comment_root(request):
"""
List all comments, or create a new comment.
@@ -196,8 +198,11 @@ The root of our API is going to be a view that supports listing all the existing
else:
return JSONResponse(serializer.errors, status=400)
+Note that because we want to be able to POST to this view from clients that won't have a CSRF token we need to mark the view as `csrf_exempt`. This isn't something that you'd normally want to do, and REST framework views actually use more sensible behavior than this, but it'll do for our purposes right now.
+
We'll also need a view which corrosponds to an individual comment, and can be used to retrieve, update or delete the comment.
+ @csrf_exempt
def comment_instance(request, pk):
"""
Retrieve, update or delete a comment instance.
--
cgit v1.2.3
From 6fc5581a8fba45fe22920e65b2d0790d483a8378 Mon Sep 17 00:00:00 2001
From: Tom Christie
Date: Tue, 25 Sep 2012 13:40:16 +0100
Subject: Add readonly 'id' field
---
docs/tutorial/1-serialization.md | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
(limited to 'docs')
diff --git a/docs/tutorial/1-serialization.md b/docs/tutorial/1-serialization.md
index 04942834..cd4b7558 100644
--- a/docs/tutorial/1-serialization.md
+++ b/docs/tutorial/1-serialization.md
@@ -67,7 +67,7 @@ For the purposes of this tutorial we're going to start by creating a simple `Com
from django.db import models
- class Comment(models.Model):
+ class Comment(models.Model):
email = models.EmailField()
content = models.CharField(max_length=200)
created = models.DateTimeField(auto_now_add=True)
@@ -85,6 +85,7 @@ We're going to create a simple Web API that we can use to edit these comment obj
class CommentSerializer(serializers.Serializer):
+ id = serializers.IntegerField(readonly=True)
email = serializers.EmailField()
content = serializers.CharField(max_length=200)
created = serializers.DateTimeField()
@@ -128,13 +129,13 @@ We've now got a few comment instances to play with. Let's take a look at serial
serializer = CommentSerializer(instance=c1)
serializer.data
- # {'email': u'leila@example.com', 'content': u'nothing to say', 'created': datetime.datetime(2012, 8, 22, 16, 20, 9, 822774, tzinfo=)}
+ # {'id': 1, 'email': u'leila@example.com', 'content': u'nothing to say', 'created': datetime.datetime(2012, 8, 22, 16, 20, 9, 822774, tzinfo=)}
At this point we've translated the model instance into python native datatypes. To finalise the serialization process we render the data into `json`.
stream = JSONRenderer().render(serializer.data)
stream
- # '{"email": "leila@example.com", "content": "nothing to say", "created": "2012-08-22T16:20:09.822"}'
+ # '{"id": 1, "email": "leila@example.com", "content": "nothing to say", "created": "2012-08-22T16:20:09.822"}'
Deserialization is similar. First we parse a stream into python native datatypes...
--
cgit v1.2.3