From bd8360c826b7a922eeb6226beb17853cfadb466c Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Wed, 17 Oct 2012 14:02:30 +0100 Subject: Highlight use of permissions alnog with authentication --- docs/api-guide/authentication.md | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'docs') diff --git a/docs/api-guide/authentication.md b/docs/api-guide/authentication.md index 71f48163..959feaa6 100644 --- a/docs/api-guide/authentication.md +++ b/docs/api-guide/authentication.md @@ -16,6 +16,12 @@ The `request.user` property will typically be set to an instance of the `contrib The `request.auth` property is used for any additional authentication information, for example, it may be used to represent an authentication token that the request was signed with. +--- + +**Note:** Don't forget that authentication by itself wont allow or disallow an incoming request, it simply identifies the credentials that the request was made with. For information on how to setup the permission polices for your API please see the [permissions documentation][permission]. + +--- + ## How authentication is determined The authentication policy is always defined as a list of classes. REST framework will attempt to authenticate with each class in the list, and will set `request.user` and `request.auth` using the return value of the first class that successfully authenticates. -- cgit v1.2.3 From 4c17d1441f184eabea9000155f07445bcc2aa14c Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Wed, 17 Oct 2012 14:59:37 +0100 Subject: Add `Unauthenticated` exception. --- docs/api-guide/exceptions.md | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'docs') diff --git a/docs/api-guide/exceptions.md b/docs/api-guide/exceptions.md index c3bdb7b9..f5dff94a 100644 --- a/docs/api-guide/exceptions.md +++ b/docs/api-guide/exceptions.md @@ -49,11 +49,19 @@ Raised if the request contains malformed data when accessing `request.DATA` or ` By default this exception results in a response with the HTTP status code "400 Bad Request". +## Unauthenticated + +**Signature:** `Unauthenticated(detail=None)` + +Raised when an unauthenticated incoming request fails the permission checks. + +By default this exception results in a response with the HTTP status code "401 Unauthenticated", but it may also result in a "403 Forbidden" response, depending on the authentication scheme in use. See the [authentication documentation][authentication] for more details. + ## PermissionDenied **Signature:** `PermissionDenied(detail=None)` -Raised when an incoming request fails the permission checks. +Raised when an authenticated incoming request fails the permission checks. By default this exception results in a response with the HTTP status code "403 Forbidden". @@ -81,4 +89,5 @@ Raised when an incoming request fails the throttling checks. By default this exception results in a response with the HTTP status code "429 Too Many Requests". -[cite]: http://www.doughellmann.com/articles/how-tos/python-exception-handling/index.html \ No newline at end of file +[cite]: http://www.doughellmann.com/articles/how-tos/python-exception-handling/index.html +[authentication]: authentication.md \ No newline at end of file -- cgit v1.2.3 From 5ae49a4ec4ccfdab13bc848ecd175d44ecaf4ed1 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Wed, 17 Oct 2012 14:59:53 +0100 Subject: Add docs for 401 vs 403 responses --- docs/api-guide/authentication.md | 72 ++++++++++++++++++++++++++++++++-------- 1 file changed, 58 insertions(+), 14 deletions(-) (limited to 'docs') diff --git a/docs/api-guide/authentication.md b/docs/api-guide/authentication.md index 959feaa6..9c61c25f 100644 --- a/docs/api-guide/authentication.md +++ b/docs/api-guide/authentication.md @@ -8,7 +8,7 @@ Authentication is the mechanism of associating an incoming request with a set of identifying credentials, such as the user the request came from, or the token that it was signed with. The [permission] and [throttling] policies can then use those credentials to determine if the request should be permitted. -REST framework provides a number of authentication policies out of the box, and also allows you to implement custom policies. +REST framework provides a number of authentication schemes out of the box, and also allows you to implement custom schemes. Authentication will run the first time either the `request.user` or `request.auth` properties are accessed, and determines how those properties are initialized. @@ -18,21 +18,21 @@ The `request.auth` property is used for any additional authentication informatio --- -**Note:** Don't forget that authentication by itself wont allow or disallow an incoming request, it simply identifies the credentials that the request was made with. For information on how to setup the permission polices for your API please see the [permissions documentation][permission]. +**Note:** Don't forget that **authentication by itself won't allow or disallow an incoming request**, it simply identifies the credentials that the request was made with. For information on how to setup the permission polices for your API please see the [permissions documentation][permission]. --- ## How authentication is determined -The authentication policy is always defined as a list of classes. REST framework will attempt to authenticate with each class in the list, and will set `request.user` and `request.auth` using the return value of the first class that successfully authenticates. +The authentication schemes are always defined as a list of classes. REST framework will attempt to authenticate with each class in the list, and will set `request.user` and `request.auth` using the return value of the first class that successfully authenticates. If no class authenticates, `request.user` will be set to an instance of `django.contrib.auth.models.AnonymousUser`, and `request.auth` will be set to `None`. The value of `request.user` and `request.auth` for unauthenticated requests can be modified using the `UNAUTHENTICATED_USER` and `UNAUTHENTICATED_TOKEN` settings. -## Setting the authentication policy +## Setting the authentication scheme -The default authentication policy may be set globally, using the `DEFAULT_AUTHENTICATION` setting. For example. +The default authentication schemes may be set globally, using the `DEFAULT_AUTHENTICATION` setting. For example. REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION': ( @@ -41,7 +41,7 @@ The default authentication policy may be set globally, using the `DEFAULT_AUTHEN ) } -You can also set the authentication policy on a per-view basis, using the `APIView` class based views. +You can also set the authentication scheme on a per-view basis, using the `APIView` class based views. class ExampleView(APIView): authentication_classes = (SessionAuthentication, UserBasicAuthentication) @@ -66,24 +66,43 @@ Or, if you're using the `@api_view` decorator with function based views. } return Response(content) +## Unauthorized and Forbidden responses + +When an unauthenticated request is denied permission there are two different error codes that may be appropriate. + +* [HTTP 401 Unauthorized][http401] +* [HTTP 403 Permission Denied][http403] + +The kind of response that will be used depends on the type of authentication scheme in use, and the ordering of the authentication classes. + +Although multiple authentication schemes may be in use, only one scheme may be used to determine the type of response. **The first authentication class set on the view is given priority when determining the type of response**. + +Note that when a *successfully authenticated* request is denied permission, a `403 Permission Denied` response will always be used, regardless of the authentication scheme. + +--- + # API Reference ## BasicAuthentication -This policy uses [HTTP Basic Authentication][basicauth], signed against a user's username and password. Basic authentication is generally only appropriate for testing. +This authentication scheme uses [HTTP Basic Authentication][basicauth], signed against a user's username and password. Basic authentication is generally only appropriate for testing. If successfully authenticated, `BasicAuthentication` provides the following credentials. * `request.user` will be a `django.contrib.auth.models.User` instance. * `request.auth` will be `None`. +Unauthenticated responses that are denied permission will result in an `HTTP 401 Unauthenticated` response with an appropriate WWW-Authenticate header. For example: + + WWW-Authenticate: Basic realm="api" + **Note:** If you use `BasicAuthentication` in production you must ensure that your API is only available over `https` only. You should also ensure that your API clients will always re-request the username and password at login, and will never store those details to persistent storage. ## TokenAuthentication -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. +This authentication scheme 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 `rest_framework.authtoken` in your `INSTALLED_APPS` setting. +To use the `TokenAuthentication` scheme, include `rest_framework.authtoken` in your `INSTALLED_APPS` setting. You'll also need to create tokens for your users. @@ -101,31 +120,56 @@ If successfully authenticated, `TokenAuthentication` provides the following cred * `request.user` will be a `django.contrib.auth.models.User` instance. * `request.auth` will be a `rest_framework.tokenauth.models.BasicToken` instance. +Unauthenticated responses that are denied permission will result in an `HTTP 401 Unauthenticated` response with an appropriate WWW-Authenticate header. For example: + + WWW-Authenticate: Token + **Note:** If you use `TokenAuthentication` in production you must ensure that your API is only available over `https` only. -## OAuthAuthentication +## OAuth2Authentication -This policy uses the [OAuth 2.0][oauth] protocol to authenticate requests. OAuth is appropriate for server-server setups, such as when you want to allow a third-party service to access your API on a user's behalf. +This authentication scheme uses the [OAuth 2.0][oauth] protocol to authenticate requests. OAuth is appropriate for server-server setups, such as when you want to allow a third-party service to access your API on a user's behalf. -If successfully authenticated, `OAuthAuthentication` provides the following credentials. +If successfully authenticated, `OAuth2Authentication` provides the following credentials. * `request.user` will be a `django.contrib.auth.models.User` instance. * `request.auth` will be a `rest_framework.models.OAuthToken` instance. +**TODO**: Note type of response (401 vs 403) + +**TODO**: Implement OAuth2Authentication, using django-oauth2-provider. + ## SessionAuthentication -This policy uses Django's default session backend for authentication. Session authentication is appropriate for AJAX clients that are running in the same session context as your website. +This authentication scheme uses Django's default session backend for authentication. Session authentication is appropriate for AJAX clients that are running in the same session context as your website. If successfully authenticated, `SessionAuthentication` provides the following credentials. * `request.user` will be a `django.contrib.auth.models.User` instance. * `request.auth` will be `None`. +Unauthenticated responses that are denied permission will result in an `HTTP 403 Forbidden` response. + +--- + # Custom authentication -To implement a custom authentication policy, subclass `BaseAuthentication` and override the `.authenticate(self, request)` method. The method should return a two-tuple of `(user, auth)` if authentication succeeds, or `None` otherwise. +To implement a custom authentication scheme, subclass `BaseAuthentication` and override the `.authenticate(self, request)` method. The method should return a two-tuple of `(user, auth)` if authentication succeeds, or `None` otherwise. + +In some circumstances instead of returning `None`, you may want to raise an `Unauthenticated` exception from the `.authenticate()` method. + +Typically the approach you should take is: + +* If authentication is not attempted, return `None`. Any other authentication schemes also in use will still be checked. +* If authentication is attempted but fails, raise an `Unauthenticated` exception. An error response will be returned immediately, without checking any other authentication schemes. + +You *may* also override the `.authentication_header(self, request)` method. If implemented, it should return a string that will be used as the value of the `WWW-Authenticate` header in a `HTTP 401 Unauthenticated` response. + +If the `.authentication_header()` method is not overridden, the authentication scheme will return `HTTP 403 Forbidden` responses when an unauthenticated request is denied access. [cite]: http://jacobian.org/writing/rest-worst-practices/ +[http401]: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.2 +[http403]: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.4 [basicauth]: http://tools.ietf.org/html/rfc2617 [oauth]: http://oauth.net/2/ [permission]: permissions.md -- cgit v1.2.3 From a4d500ba107466e8d44a82ed8ca632a3ea81a016 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Wed, 17 Oct 2012 15:10:11 +0100 Subject: Use correct status code --- docs/api-guide/authentication.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'docs') diff --git a/docs/api-guide/authentication.md b/docs/api-guide/authentication.md index 9c61c25f..06f428c0 100644 --- a/docs/api-guide/authentication.md +++ b/docs/api-guide/authentication.md @@ -92,7 +92,7 @@ If successfully authenticated, `BasicAuthentication` provides the following cred * `request.user` will be a `django.contrib.auth.models.User` instance. * `request.auth` will be `None`. -Unauthenticated responses that are denied permission will result in an `HTTP 401 Unauthenticated` response with an appropriate WWW-Authenticate header. For example: +Unauthenticated responses that are denied permission will result in an `HTTP 401 Unauthorized` response with an appropriate WWW-Authenticate header. For example: WWW-Authenticate: Basic realm="api" @@ -120,7 +120,7 @@ If successfully authenticated, `TokenAuthentication` provides the following cred * `request.user` will be a `django.contrib.auth.models.User` instance. * `request.auth` will be a `rest_framework.tokenauth.models.BasicToken` instance. -Unauthenticated responses that are denied permission will result in an `HTTP 401 Unauthenticated` response with an appropriate WWW-Authenticate header. For example: +Unauthenticated responses that are denied permission will result in an `HTTP 401 Unauthorized` response with an appropriate WWW-Authenticate header. For example: WWW-Authenticate: Token @@ -163,7 +163,7 @@ Typically the approach you should take is: * If authentication is not attempted, return `None`. Any other authentication schemes also in use will still be checked. * If authentication is attempted but fails, raise an `Unauthenticated` exception. An error response will be returned immediately, without checking any other authentication schemes. -You *may* also override the `.authentication_header(self, request)` method. If implemented, it should return a string that will be used as the value of the `WWW-Authenticate` header in a `HTTP 401 Unauthenticated` response. +You *may* also override the `.authentication_header(self, request)` method. If implemented, it should return a string that will be used as the value of the `WWW-Authenticate` header in a `HTTP 401 Unauthorized` response. If the `.authentication_header()` method is not overridden, the authentication scheme will return `HTTP 403 Forbidden` responses when an unauthenticated request is denied access. -- cgit v1.2.3 From b78872b7dbb55f1aa2d21f15fbb952f0c7156326 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Wed, 17 Oct 2012 15:23:36 +0100 Subject: Use two seperate exceptions - `AuthenticationFailed`, and `NotAuthenticated` Cleaner seperation of exception and resulting HTTP response. Should result in more obvious error messages. --- docs/api-guide/authentication.md | 4 ++-- docs/api-guide/exceptions.md | 16 ++++++++++++---- 2 files changed, 14 insertions(+), 6 deletions(-) (limited to 'docs') diff --git a/docs/api-guide/authentication.md b/docs/api-guide/authentication.md index 06f428c0..3ace6519 100644 --- a/docs/api-guide/authentication.md +++ b/docs/api-guide/authentication.md @@ -156,12 +156,12 @@ Unauthenticated responses that are denied permission will result in an `HTTP 403 To implement a custom authentication scheme, subclass `BaseAuthentication` and override the `.authenticate(self, request)` method. The method should return a two-tuple of `(user, auth)` if authentication succeeds, or `None` otherwise. -In some circumstances instead of returning `None`, you may want to raise an `Unauthenticated` exception from the `.authenticate()` method. +In some circumstances instead of returning `None`, you may want to raise an `AuthenticationFailed` exception from the `.authenticate()` method. Typically the approach you should take is: * If authentication is not attempted, return `None`. Any other authentication schemes also in use will still be checked. -* If authentication is attempted but fails, raise an `Unauthenticated` exception. An error response will be returned immediately, without checking any other authentication schemes. +* If authentication is attempted but fails, raise a `AuthenticationFailed` exception. An error response will be returned immediately, without checking any other authentication schemes. You *may* also override the `.authentication_header(self, request)` method. If implemented, it should return a string that will be used as the value of the `WWW-Authenticate` header in a `HTTP 401 Unauthorized` response. diff --git a/docs/api-guide/exceptions.md b/docs/api-guide/exceptions.md index f5dff94a..c30f586a 100644 --- a/docs/api-guide/exceptions.md +++ b/docs/api-guide/exceptions.md @@ -49,11 +49,19 @@ Raised if the request contains malformed data when accessing `request.DATA` or ` By default this exception results in a response with the HTTP status code "400 Bad Request". -## Unauthenticated +## AuthenticationFailed -**Signature:** `Unauthenticated(detail=None)` +**Signature:** `AuthenticationFailed(detail=None)` -Raised when an unauthenticated incoming request fails the permission checks. +Raised when an incoming request includes incorrect authentication. + +By default this exception results in a response with the HTTP status code "401 Unauthenticated", but it may also result in a "403 Forbidden" response, depending on the authentication scheme in use. See the [authentication documentation][authentication] for more details. + +## NotAuthenticated + +**Signature:** `NotAuthenticated(detail=None)` + +Raised when an unauthenticated request fails the permission checks. By default this exception results in a response with the HTTP status code "401 Unauthenticated", but it may also result in a "403 Forbidden" response, depending on the authentication scheme in use. See the [authentication documentation][authentication] for more details. @@ -61,7 +69,7 @@ By default this exception results in a response with the HTTP status code "401 U **Signature:** `PermissionDenied(detail=None)` -Raised when an authenticated incoming request fails the permission checks. +Raised when an authenticated request fails the permission checks. By default this exception results in a response with the HTTP status code "403 Forbidden". -- cgit v1.2.3 From 957700ecfb36322a8ea40ea473dc43ff1e92592f Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Tue, 13 Nov 2012 11:26:45 +0000 Subject: Remove OAuth2 from docs --- docs/api-guide/authentication.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/api-guide/authentication.md b/docs/api-guide/authentication.md index c87ba83e..b2323d62 100644 --- a/docs/api-guide/authentication.md +++ b/docs/api-guide/authentication.md @@ -126,7 +126,7 @@ Unauthenticated responses that are denied permission will result in an `HTTP 401 **Note:** If you use `TokenAuthentication` in production you must ensure that your API is only available over `https` only. -## OAuth2Authentication + ## SessionAuthentication -- cgit v1.2.3 From 0756ca1f42cd7768f9450ec004a65664678ddf82 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Wed, 16 Jan 2013 14:35:30 +0000 Subject: Added @steve-gregory for nullable slug relation tests. See: #585 --- 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 b0b00c12..68d07f20 100644 --- a/docs/topics/credits.md +++ b/docs/topics/credits.md @@ -91,6 +91,7 @@ The following people have helped make REST framework great. * Richard Wackerbarth - [wackerbarth] * Johannes Spielmann - [shezi] * James Cleveland - [radiosilence] +* Steve Gregory - [steve-gregory] Many thanks to everyone who's contributed to the project. @@ -217,3 +218,4 @@ You can also contact [@_tomchristie][twitter] directly on twitter. [wackerbarth]: https://github.com/wackerbarth [shezi]: https://github.com/shezi [radiosilence]: https://github.com/radiosilence +[steve-gregory]: https://github.com/steve-gregory -- cgit v1.2.3 From fecfe57aeff8a10841b0ff1f51a7e4747ce897fb Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Wed, 16 Jan 2013 14:36:37 +0000 Subject: Updated release notes. --- docs/topics/release-notes.md | 1 + 1 file changed, 1 insertion(+) (limited to 'docs') diff --git a/docs/topics/release-notes.md b/docs/topics/release-notes.md index f43dc1d3..74c3b74a 100644 --- a/docs/topics/release-notes.md +++ b/docs/topics/release-notes.md @@ -19,6 +19,7 @@ Major version numbers (x.0.0) are reserved for project milestones. No major poi ### Master * Support json encoding of timedelta objects. +* Bugfix: Support nullable FKs with `SlugRelatedField`. ### 2.1.16 -- cgit v1.2.3 From 0f0a07b732a4bd90957c08b01d51e70c7e739d5d Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Wed, 16 Jan 2013 14:41:57 +0000 Subject: Note changes to Decimal rendering to json behavior. Fixes #582. --- docs/topics/release-notes.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/topics/release-notes.md b/docs/topics/release-notes.md index 74c3b74a..e00a5e93 100644 --- a/docs/topics/release-notes.md +++ b/docs/topics/release-notes.md @@ -25,13 +25,15 @@ Major version numbers (x.0.0) are reserved for project milestones. No major poi **Date**: 14th Jan 2013 -* Deprecate django.utils.simplejson in favor of Python 2.6's built-in json module. +* Deprecate `django.utils.simplejson` in favor of Python 2.6's built-in json module. * Bugfix: `auto_now`, `auto_now_add` and other `editable=False` fields now default to read-only. * Bugfix: PK fields now only default to read-only if they are an AutoField or if `editable=False`. * Bugfix: Validation errors instead of exceptions when serializers receive incorrect types. * Bugfix: Validation errors instead of exceptions when related fields receive incorrect types. * Bugfix: Handle ObjectDoesNotExist exception when serializing null reverse one-to-one +**Note**: Prior to 2.1.16, The Decimals would render in JSON using floating point if `simplejson` was installed, but otherwise render using string notation. Now that use of `simplejson` has been deprecated, Decimals will consistently render using string notation. See [#582] for more details. + ### 2.1.15 **Date**: 3rd Jan 2013 @@ -324,3 +326,4 @@ This change will not affect user code, so long as it's following the recommended [staticfiles13]: https://docs.djangoproject.com/en/1.3/howto/static-files/#with-a-template-tag [2.1.0-notes]: https://groups.google.com/d/topic/django-rest-framework/Vv2M0CMY9bg/discussion [announcement]: rest-framework-2-announcement.md +[#582]: https://github.com/tomchristie/django-rest-framework/issues/582 -- cgit v1.2.3 From 55cc7452546f44d48fd68b81eebc1eed75eff1df Mon Sep 17 00:00:00 2001 From: Federico Capoano Date: Wed, 16 Jan 2013 17:10:46 +0100 Subject: Update docs/api-guide/authentication.md Added mod_wsgi specific instructions--- docs/api-guide/authentication.md | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'docs') diff --git a/docs/api-guide/authentication.md b/docs/api-guide/authentication.md index afd9a261..e91f6c2e 100644 --- a/docs/api-guide/authentication.md +++ b/docs/api-guide/authentication.md @@ -60,6 +60,17 @@ Or, if you're using the `@api_view` decorator with function based views. } return Response(content) +## Apache mod_wsgi Specific Configuration + +Unlike other HTTP headers, the authorisation header is not passed through to a WSGI application by default. This is the case as doing so could leak information about passwords through to a WSGI application which should not be able to see them when Apache is performing authentication... + +If it is desired that the WSGI application be responsible for handling user authentication, then it is necessary to explicitly configure mod_wsgi to pass the required headers through to the application. This can be done by specifying the WSGIPassAuthorization directive in the appropriate context and setting it to 'On'. + + # this can go in either server config, virtual host, directory or .htaccess + WSGIPassAuthorization On + +[cite]: http://code.google.com/p/modwsgi/wiki/ConfigurationDirectives#WSGIPassAuthorization + # API Reference ## BasicAuthentication -- cgit v1.2.3 From f19d4ea8b126650bc23af822acd3d6af9c7fb632 Mon Sep 17 00:00:00 2001 From: Federico Capoano Date: Wed, 16 Jan 2013 17:17:07 +0100 Subject: Update docs/api-guide/authentication.md refined mod_wsgi--- docs/api-guide/authentication.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'docs') diff --git a/docs/api-guide/authentication.md b/docs/api-guide/authentication.md index e91f6c2e..330cf7a4 100644 --- a/docs/api-guide/authentication.md +++ b/docs/api-guide/authentication.md @@ -62,14 +62,14 @@ Or, if you're using the `@api_view` decorator with function based views. ## Apache mod_wsgi Specific Configuration -Unlike other HTTP headers, the authorisation header is not passed through to a WSGI application by default. This is the case as doing so could leak information about passwords through to a WSGI application which should not be able to see them when Apache is performing authentication... +Unlike other HTTP headers, the authorisation header is not passed through to a WSGI application by default. This is the case as doing so could leak information about passwords through to a WSGI application which should not be able to see them when Apache is performing authentication. If it is desired that the WSGI application be responsible for handling user authentication, then it is necessary to explicitly configure mod_wsgi to pass the required headers through to the application. This can be done by specifying the WSGIPassAuthorization directive in the appropriate context and setting it to 'On'. # this can go in either server config, virtual host, directory or .htaccess WSGIPassAuthorization On -[cite]: http://code.google.com/p/modwsgi/wiki/ConfigurationDirectives#WSGIPassAuthorization +[Reference to official mod_wsgi documentation][mod_wsgi_official] # API Reference @@ -157,3 +157,4 @@ To implement a custom authentication policy, subclass `BaseAuthentication` and o [permission]: permissions.md [throttling]: throttling.md [csrf-ajax]: https://docs.djangoproject.com/en/dev/ref/contrib/csrf/#ajax +[mod_wsgi_official]: http://code.google.com/p/modwsgi/wiki/ConfigurationDirectives#WSGIPassAuthorization -- cgit v1.2.3 From ed1375485906f261449b92fe6e20715530625d07 Mon Sep 17 00:00:00 2001 From: Michael Elovskikh Date: Thu, 17 Jan 2013 17:17:53 +0600 Subject: Added PATCH HTTP method to the docs --- docs/api-guide/authentication.md | 2 +- docs/api-guide/requests.md | 4 ++-- docs/api-guide/views.md | 2 +- docs/topics/browsable-api.md | 3 ++- docs/topics/browser-enhancements.md | 8 ++++---- 5 files changed, 10 insertions(+), 9 deletions(-) (limited to 'docs') diff --git a/docs/api-guide/authentication.md b/docs/api-guide/authentication.md index afd9a261..2d34d788 100644 --- a/docs/api-guide/authentication.md +++ b/docs/api-guide/authentication.md @@ -134,7 +134,7 @@ If successfully authenticated, `SessionAuthentication` provides the following cr * `request.user` will be a Django `User` instance. * `request.auth` will be `None`. -If you're using an AJAX style API with SessionAuthentication, you'll need to make sure you include a valid CSRF token for any "unsafe" HTTP method calls, such as `PUT`, `POST` or `DELETE` requests. See the [Django CSRF documentation][csrf-ajax] for more details. +If you're using an AJAX style API with SessionAuthentication, you'll need to make sure you include a valid CSRF token for any "unsafe" HTTP method calls, such as `PUT`, `PATCH`, `POST` or `DELETE` requests. See the [Django CSRF documentation][csrf-ajax] for more details. # Custom authentication diff --git a/docs/api-guide/requests.md b/docs/api-guide/requests.md index 72932f5d..39a34fcf 100644 --- a/docs/api-guide/requests.md +++ b/docs/api-guide/requests.md @@ -83,13 +83,13 @@ You won't typically need to access this property. # Browser enhancements -REST framework supports a few browser enhancements such as browser-based `PUT` and `DELETE` forms. +REST framework supports a few browser enhancements such as browser-based `PUT`, `PATCH` and `DELETE` forms. ## .method `request.method` returns the **uppercased** string representation of the request's HTTP method. -Browser-based `PUT` and `DELETE` forms are transparently supported. +Browser-based `PUT`, `PATCH` and `DELETE` forms are transparently supported. For more information see the [browser enhancements documentation]. diff --git a/docs/api-guide/views.md b/docs/api-guide/views.md index d1e42ec1..574020f9 100644 --- a/docs/api-guide/views.md +++ b/docs/api-guide/views.md @@ -85,7 +85,7 @@ The following methods are called before dispatching to the handler method. ## Dispatch methods The following methods are called directly by the view's `.dispatch()` method. -These perform any actions that need to occur before or after calling the handler methods such as `.get()`, `.post()`, `put()` and `.delete()`. +These perform any actions that need to occur before or after calling the handler methods such as `.get()`, `.post()`, `put()`, `patch()` and `.delete()`. ### .initial(self, request, \*args, **kwargs) diff --git a/docs/topics/browsable-api.md b/docs/topics/browsable-api.md index 9fe82e69..479987a1 100644 --- a/docs/topics/browsable-api.md +++ b/docs/topics/browsable-api.md @@ -5,7 +5,7 @@ > — [Alfred North Whitehead][cite], An Introduction to Mathematics (1911) -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`. +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`, `PATCH` and `DELETE`. ## URLs @@ -79,6 +79,7 @@ The context that's available to the template: * `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) +* `patch_form` : A form instance for use by the PATCH form (if allowed) * `request` : The request object * `response` : The response object * `version` : The version of Django REST Framework diff --git a/docs/topics/browser-enhancements.md b/docs/topics/browser-enhancements.md index 6a11f0fa..3949f7a6 100644 --- a/docs/topics/browser-enhancements.md +++ b/docs/topics/browser-enhancements.md @@ -1,12 +1,12 @@ # Browser enhancements -> "There are two noncontroversial uses for overloaded POST. The first is to *simulate* HTTP's uniform interface for clients like web browsers that don't support PUT or DELETE" +> "There are two noncontroversial uses for overloaded POST. The first is to *simulate* HTTP's uniform interface for clients like web browsers that don't support PUT, PATCH or DELETE" > > — [RESTful Web Services][cite], Leonard Richardson & Sam Ruby. -## Browser based PUT, DELETE, etc... +## Browser based PUT, PATCH, DELETE, etc... -REST framework supports browser-based `PUT`, `DELETE` and other methods, by +REST framework supports browser-based `PUT`, `PATCH`, `DELETE` and other methods, by overloading `POST` requests using a hidden form field. Note that this is the same strategy as is used in [Ruby on Rails][rails]. @@ -51,7 +51,7 @@ the view. This is a more concise than using the `accept` override, but it also gives you less control. (For example you can't specify any media type parameters) -## Doesn't HTML5 support PUT and DELETE forms? +## Doesn't HTML5 support PUT, PATCH and DELETE forms? Nope. It was at one point intended to support `PUT` and `DELETE` forms, but was later [dropped from the spec][html5]. There remains -- cgit v1.2.3 From 80a8d0f2793835f1a33be309ae3e51d4b7dbae39 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Fri, 18 Jan 2013 14:04:26 +0000 Subject: Update docs to reference DabApps commercial support --- docs/index.md | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'docs') diff --git a/docs/index.md b/docs/index.md index 497f1900..3ed11c02 100644 --- a/docs/index.md +++ b/docs/index.md @@ -132,9 +132,9 @@ Run the tests: ## Support -For support please see the [REST framework discussion group][group], or try the `#restframework` channel on `irc.freenode.net`. +For support please see the [REST framework discussion group][group], try the `#restframework` channel on `irc.freenode.net`, or raise a question on [Stack Overflow][stack-overflow], making sure to include the ['django-rest-framework'][django-rest-framework-tag] tag. -Paid support is also available from [DabApps], and can include work on REST framework core, or support with building your REST framework API. Please contact [Tom Christie][email] if you'd like to discuss commercial support options. +[Paid support is available][paid-support] from [DabApps][dabapps], and can include work on REST framework core, or support with building your REST framework API. Please [contact DabApps][contact-dabapps] if you'd like to discuss commercial support options. ## License @@ -209,5 +209,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. [credits]: topics/credits.md [group]: https://groups.google.com/forum/?fromgroups#!forum/django-rest-framework -[DabApps]: http://dabapps.com -[email]: mailto:tom@tomchristie.com +[stack-overflow]: http://stackoverflow.com/ +[django-rest-framework-tag]: http://stackoverflow.com/questions/tagged/django-rest-framework +[django-tag]: http://stackoverflow.com/questions/tagged/django +[paid-support]: http://dabapps.com/services/build/api-development/ +[dabapps]: http://dabapps.com +[contact-dabapps]: http://dabapps.com/contact/ -- cgit v1.2.3 From 06724017810c84a36521762a6f025bf4d3007006 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Fri, 18 Jan 2013 22:00:59 +0000 Subject: Update release notes. --- docs/topics/release-notes.md | 1 + 1 file changed, 1 insertion(+) (limited to 'docs') diff --git a/docs/topics/release-notes.md b/docs/topics/release-notes.md index e00a5e93..bbe11fac 100644 --- a/docs/topics/release-notes.md +++ b/docs/topics/release-notes.md @@ -19,6 +19,7 @@ Major version numbers (x.0.0) are reserved for project milestones. No major poi ### Master * Support json encoding of timedelta objects. +* Bugfix: Return proper validation errors when incorrect types supplied for relational fields. * Bugfix: Support nullable FKs with `SlugRelatedField`. ### 2.1.16 -- cgit v1.2.3 From bd089836a138bc845eac5f89a071d2768bcf2e0e Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Fri, 18 Jan 2013 22:01:33 +0000 Subject: Note on setting ContentType. Fixes #589. Refs #586. --- docs/api-guide/parsers.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'docs') diff --git a/docs/api-guide/parsers.md b/docs/api-guide/parsers.md index de968557..3a1918f4 100644 --- a/docs/api-guide/parsers.md +++ b/docs/api-guide/parsers.md @@ -14,6 +14,18 @@ REST framework includes a number of built in Parser classes, that allow you to a The set of valid parsers for a view is always defined as a list of classes. When either `request.DATA` or `request.FILES` is accessed, REST framework will examine the `Content-Type` header on the incoming request, and determine which parser to use to parse the request content. +--- + +**Note**: When developing client applications always remember to make sure you're setting the `Content-Type` header when sending data in an HTTP request. + +If you don't set the content type, most clients will default to using `'application/x-www-form-urlencoded'`, which may not be what you wanted. + +As an example, if you are sending `json` encoded data using jQuery with the [.ajax() method][jquery-ajax], you should make sure to include the `contentType: 'application/json'` setting. + +If you're working with the API using the command line tool `curl`, you can use the `-H` flag to include a `ContentType` header. For example, to set the content type to `json` use `-H 'content-type: application/json'`. + +--- + ## Setting the parsers The default set of parsers may be set globally, using the `DEFAULT_PARSER_CLASSES` setting. For example, the following settings would allow requests with `YAML` content. @@ -169,6 +181,7 @@ The following third party packages are also available. [MessagePack][messagepack] is a fast, efficient binary serialization format. [Juan Riaza][juanriaza] maintains the [djangorestframework-msgpack][djangorestframework-msgpack] package which provides MessagePack renderer and parser support for REST framework. +[jquery-ajax]: http://api.jquery.com/jQuery.ajax/ [cite]: https://groups.google.com/d/topic/django-developers/dxI4qVzrBY4/discussion [messagepack]: https://github.com/juanriaza/django-rest-framework-msgpack [juanriaza]: https://github.com/juanriaza -- cgit v1.2.3 From 15ad94c6111735044dd6a38a9b48d23a22b8b18f Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Fri, 18 Jan 2013 22:06:41 +0000 Subject: Drop the curl notes. Unnecessary. --- docs/api-guide/parsers.md | 2 -- 1 file changed, 2 deletions(-) (limited to 'docs') diff --git a/docs/api-guide/parsers.md b/docs/api-guide/parsers.md index 3a1918f4..0cd01639 100644 --- a/docs/api-guide/parsers.md +++ b/docs/api-guide/parsers.md @@ -22,8 +22,6 @@ If you don't set the content type, most clients will default to using `'applicat As an example, if you are sending `json` encoded data using jQuery with the [.ajax() method][jquery-ajax], you should make sure to include the `contentType: 'application/json'` setting. -If you're working with the API using the command line tool `curl`, you can use the `-H` flag to include a `ContentType` header. For example, to set the content type to `json` use `-H 'content-type: application/json'`. - --- ## Setting the parsers -- cgit v1.2.3 From 73b69b9bb6f92f0d674c10420ac462b51cad233d Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Fri, 18 Jan 2013 22:26:36 +0000 Subject: Rephrasing. --- docs/api-guide/authentication.md | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'docs') diff --git a/docs/api-guide/authentication.md b/docs/api-guide/authentication.md index 330cf7a4..c0f9c072 100644 --- a/docs/api-guide/authentication.md +++ b/docs/api-guide/authentication.md @@ -60,17 +60,15 @@ Or, if you're using the `@api_view` decorator with function based views. } return Response(content) -## Apache mod_wsgi Specific Configuration +## Apache mod_wsgi specific configuration -Unlike other HTTP headers, the authorisation header is not passed through to a WSGI application by default. This is the case as doing so could leak information about passwords through to a WSGI application which should not be able to see them when Apache is performing authentication. +Note that if deploying to [Apache using mod_wsgi][mod_wsgi_official], the authorization header is not passed through to a WSGI application by default, as it is assumed that authentication will be handled by Apache, rather than at an application level. -If it is desired that the WSGI application be responsible for handling user authentication, then it is necessary to explicitly configure mod_wsgi to pass the required headers through to the application. This can be done by specifying the WSGIPassAuthorization directive in the appropriate context and setting it to 'On'. +If you are deploying to Apache, and using any non-session based authentication, you will need to explicitly configure mod_wsgi to pass the required headers through to the application. This can be done by specifying the `WSGIPassAuthorization` directive in the appropriate context and setting it to `'On'`. # this can go in either server config, virtual host, directory or .htaccess WSGIPassAuthorization On -[Reference to official mod_wsgi documentation][mod_wsgi_official] - # API Reference ## BasicAuthentication -- cgit v1.2.3 From 4b61ead53ff3d13e55346e07317612096f704af8 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Fri, 18 Jan 2013 22:30:03 +0000 Subject: Added @nemesisdesign, for documentation on Apache mod_wsgi setup. Thanks! Refs #588. --- 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 68d07f20..6529813f 100644 --- a/docs/topics/credits.md +++ b/docs/topics/credits.md @@ -92,6 +92,7 @@ The following people have helped make REST framework great. * Johannes Spielmann - [shezi] * James Cleveland - [radiosilence] * Steve Gregory - [steve-gregory] +* Federico Capoano - [nemesisdesign] Many thanks to everyone who's contributed to the project. @@ -219,3 +220,4 @@ You can also contact [@_tomchristie][twitter] directly on twitter. [shezi]: https://github.com/shezi [radiosilence]: https://github.com/radiosilence [steve-gregory]: https://github.com/steve-gregory +[nemesisdesign]: https://github.com/nemesisdesign -- cgit v1.2.3 From af3fd098459fb559788735cb6b49a7108e11b18e Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Sat, 19 Jan 2013 15:31:21 +0000 Subject: Tweak imports in tutorial. Fixes #597. --- docs/tutorial/1-serialization.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'docs') diff --git a/docs/tutorial/1-serialization.md b/docs/tutorial/1-serialization.md index d3ada9e3..f5ff167f 100644 --- a/docs/tutorial/1-serialization.md +++ b/docs/tutorial/1-serialization.md @@ -109,7 +109,7 @@ The first thing we need to get started on our Web API is provide a way of serial from django.forms import widgets from rest_framework import serializers - from snippets import models + from snippets.models import Snippet class SnippetSerializer(serializers.Serializer): @@ -138,7 +138,7 @@ The first thing we need to get started on our Web API is provide a way of serial return instance # Create new instance - return models.Snippet(**attrs) + return Snippet(**attrs) The first part of serializer class defines the fields that get serialized/deserialized. The `restore_object` method defines how fully fledged instances get created when deserializing data. -- cgit v1.2.3 From 199fa766ff7b5c7606e8f835dcf2d1d979da38b1 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Sat, 19 Jan 2013 17:00:20 +0000 Subject: Update release notes --- docs/topics/release-notes.md | 1 + 1 file changed, 1 insertion(+) (limited to 'docs') diff --git a/docs/topics/release-notes.md b/docs/topics/release-notes.md index bbe11fac..58471a79 100644 --- a/docs/topics/release-notes.md +++ b/docs/topics/release-notes.md @@ -19,6 +19,7 @@ Major version numbers (x.0.0) are reserved for project milestones. No major poi ### Master * Support json encoding of timedelta objects. +* `format_suffix_patterns()` now supports `include` style URL patterns. * Bugfix: Return proper validation errors when incorrect types supplied for relational fields. * Bugfix: Support nullable FKs with `SlugRelatedField`. -- cgit v1.2.3 From 9b9b6529bcf3c3f39abf398597684962e5710e57 Mon Sep 17 00:00:00 2001 From: Bruno Renié Date: Sun, 20 Jan 2013 14:49:07 +0100 Subject: Fixed reference to authtoken in the docs --- docs/api-guide/authentication.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/api-guide/authentication.md b/docs/api-guide/authentication.md index c0f9c072..1b56cf44 100644 --- a/docs/api-guide/authentication.md +++ b/docs/api-guide/authentication.md @@ -102,7 +102,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 `User` instance. -* `request.auth` will be a `rest_framework.tokenauth.models.BasicToken` instance. +* `request.auth` will be a `rest_framework.authtoken.models.BasicToken` instance. **Note:** If you use `TokenAuthentication` in production you must ensure that your API is only available over `https` only. -- cgit v1.2.3 From 42fcc3599c7d6aff2b50e534af4a5efbe3ce8c47 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Sun, 20 Jan 2013 15:50:16 +0000 Subject: Added @brutasse for docs fix #600. 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 6529813f..49050196 100644 --- a/docs/topics/credits.md +++ b/docs/topics/credits.md @@ -93,6 +93,7 @@ The following people have helped make REST framework great. * James Cleveland - [radiosilence] * Steve Gregory - [steve-gregory] * Federico Capoano - [nemesisdesign] +* Bruno Renié - [brutasse] Many thanks to everyone who's contributed to the project. @@ -221,3 +222,4 @@ You can also contact [@_tomchristie][twitter] directly on twitter. [radiosilence]: https://github.com/radiosilence [steve-gregory]: https://github.com/steve-gregory [nemesisdesign]: https://github.com/nemesisdesign +[brutasse]: https://github.com/brutasse -- cgit v1.2.3 From 2c76212e5454efa4d4d02c7051055c7957497d52 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Sun, 20 Jan 2013 16:38:32 +0000 Subject: Add missing import to tutorial. Fixes #599 --- docs/tutorial/4-authentication-and-permissions.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/tutorial/4-authentication-and-permissions.md b/docs/tutorial/4-authentication-and-permissions.md index f6daebb7..35aca8c6 100644 --- a/docs/tutorial/4-authentication-and-permissions.md +++ b/docs/tutorial/4-authentication-and-permissions.md @@ -54,6 +54,8 @@ You might also want to create a few different users, to use for testing the API. Now that we've got some users to work with, we'd better add representations of those users to our API. Creating a new serializer is easy: + from django.contrib.auth.models import User + class UserSerializer(serializers.ModelSerializer): snippets = serializers.ManyPrimaryKeyRelatedField() @@ -188,4 +190,4 @@ We've now got a fairly fine-grained set of permissions on our Web API, and end p In [part 5][tut-5] of the tutorial we'll look at how we can tie everything together by creating an HTML endpoint for our hightlighted snippets, and improve the cohesion of our API by using hyperlinking for the relationships within the system. -[tut-5]: 5-relationships-and-hyperlinked-apis.md \ No newline at end of file +[tut-5]: 5-relationships-and-hyperlinked-apis.md -- cgit v1.2.3 From e29ba356f054222893655901923811bd9675d4cc Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Mon, 21 Jan 2013 17:53:27 +0000 Subject: Added @kevinastone, for work on extra test cases in #602. 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 49050196..b033ecba 100644 --- a/docs/topics/credits.md +++ b/docs/topics/credits.md @@ -94,6 +94,7 @@ The following people have helped make REST framework great. * Steve Gregory - [steve-gregory] * Federico Capoano - [nemesisdesign] * Bruno Renié - [brutasse] +* Kevin Stone - [kevinastone] Many thanks to everyone who's contributed to the project. @@ -223,3 +224,4 @@ You can also contact [@_tomchristie][twitter] directly on twitter. [steve-gregory]: https://github.com/steve-gregory [nemesisdesign]: https://github.com/nemesisdesign [brutasse]: https://github.com/brutasse +[kevinastone]: https://github.com/kevinastone -- cgit v1.2.3 From 65b62d64ec54b528b62a1500b8f6ffe216d45c09 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Mon, 21 Jan 2013 21:29:49 +0000 Subject: WWW-Authenticate responses --- docs/api-guide/authentication.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'docs') diff --git a/docs/api-guide/authentication.md b/docs/api-guide/authentication.md index 4dfcb0f1..59dc4a30 100644 --- a/docs/api-guide/authentication.md +++ b/docs/api-guide/authentication.md @@ -18,7 +18,9 @@ The `request.auth` property is used for any additional authentication informatio --- -**Note:** Don't forget that **authentication by itself won't allow or disallow an incoming request**, it simply identifies the credentials that the request was made with. For information on how to setup the permission polices for your API please see the [permissions documentation][permission]. +**Note:** Don't forget that **authentication by itself won't allow or disallow an incoming request**, it simply identifies the credentials that the request was made with. + +For information on how to setup the permission polices for your API please see the [permissions documentation][permission]. --- @@ -73,11 +75,11 @@ When an unauthenticated request is denied permission there are two different err * [HTTP 401 Unauthorized][http401] * [HTTP 403 Permission Denied][http403] -The kind of response that will be used depends on the type of authentication scheme in use, and the ordering of the authentication classes. +HTTP 401 responses must always include a `WWW-Authenticate` header, that instructs the client how to authenticate. HTTP 403 responses do not include the `WWW-Authenticate` header. -Although multiple authentication schemes may be in use, only one scheme may be used to determine the type of response. **The first authentication class set on the view is given priority when determining the type of response**. +The kind of response that will be used depends on the authentication scheme. Although multiple authentication schemes may be in use, only one scheme may be used to determine the type of response. **The first authentication class set on the view is used when determining the type of response**. -Note that when a *successfully authenticated* request is denied permission, a `403 Permission Denied` response will always be used, regardless of the authentication scheme. +Note that when a request may successfully authenticate, but still be denied permission to perform the request, in which case a `403 Permission Denied` response will always be used, regardless of the authentication scheme. --- @@ -126,8 +128,6 @@ Unauthenticated responses that are denied permission will result in an `HTTP 401 **Note:** If you use `TokenAuthentication` in production you must ensure that your API is only available over `https` only. -<<<<<<< HEAD - +The tutorial is fairly in-depth, so you should probably get a cookie and a cup of your favorite brew before getting started. If you just want a quick overview, you should head over to the [quickstart] documentation instead. --- -- cgit v1.2.3 From 896477f6509fb56ec0a946560748885f6ca6fe8d Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Mon, 28 Jan 2013 07:54:03 +0000 Subject: Added @mktums for docs fix in #621. 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 7cffbede..19a6397c 100644 --- a/docs/topics/credits.md +++ b/docs/topics/credits.md @@ -96,6 +96,7 @@ The following people have helped make REST framework great. * Bruno Renié - [brutasse] * Kevin Stone - [kevinastone] * Guglielmo Celata - [guglielmo] +* Mike Tums - [mktums] Many thanks to everyone who's contributed to the project. @@ -227,3 +228,4 @@ You can also contact [@_tomchristie][twitter] directly on twitter. [brutasse]: https://github.com/brutasse [kevinastone]: https://github.com/kevinastone [guglielmo]: https://github.com/guglielmo +[mktums]: https://github.com/mktums -- cgit v1.2.3 From e682bfa54efc391df4d6bb7cf78a2089213b8d6b Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Mon, 28 Jan 2013 08:01:54 +0000 Subject: Drop unneccessary `source=` argument. --- docs/api-guide/relations.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/api-guide/relations.md b/docs/api-guide/relations.md index 351b5e09..9f5a04b2 100644 --- a/docs/api-guide/relations.md +++ b/docs/api-guide/relations.md @@ -67,7 +67,7 @@ For example, given the following models: And a model serializer defined like this: class BookmarkSerializer(serializers.ModelSerializer): - tags = serializers.ManyRelatedField(source='tags') + tags = serializers.ManyRelatedField() class Meta: model = Bookmark -- cgit v1.2.3 From 3bcd38b7d0ddaa2c051ad230cb0d749f9737fd82 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Mon, 28 Jan 2013 09:10:23 +0000 Subject: Notes on upgrading and versioning. Fixes #620. --- docs/topics/release-notes.md | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'docs') diff --git a/docs/topics/release-notes.md b/docs/topics/release-notes.md index 0c3ebca0..84b30d85 100644 --- a/docs/topics/release-notes.md +++ b/docs/topics/release-notes.md @@ -12,6 +12,16 @@ Medium version numbers (0.x.0) may include minor API changes. You should read t Major version numbers (x.0.0) are reserved for project milestones. No major point releases are currently planned. +## Upgrading + +To upgrade Django REST framework to the latest version, use pip: + + pip install -U djangorestframework + +You can determine your currently installed version using `pip freeze`: + + pip freeze | grep djangorestframework + --- ## 2.1.x series -- cgit v1.2.3 From 180c94dc44a9cc5b882364a58b0b12a8ab430c22 Mon Sep 17 00:00:00 2001 From: Michael Elovskikh Date: Mon, 28 Jan 2013 15:54:00 +0600 Subject: Undo changes in browsable-api.md and browser-enhancements.md --- docs/topics/browsable-api.md | 3 +-- docs/topics/browser-enhancements.md | 8 ++++---- 2 files changed, 5 insertions(+), 6 deletions(-) (limited to 'docs') diff --git a/docs/topics/browsable-api.md b/docs/topics/browsable-api.md index 479987a1..9fe82e69 100644 --- a/docs/topics/browsable-api.md +++ b/docs/topics/browsable-api.md @@ -5,7 +5,7 @@ > — [Alfred North Whitehead][cite], An Introduction to Mathematics (1911) -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`, `PATCH` and `DELETE`. +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 @@ -79,7 +79,6 @@ The context that's available to the template: * `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) -* `patch_form` : A form instance for use by the PATCH form (if allowed) * `request` : The request object * `response` : The response object * `version` : The version of Django REST Framework diff --git a/docs/topics/browser-enhancements.md b/docs/topics/browser-enhancements.md index 3949f7a6..6a11f0fa 100644 --- a/docs/topics/browser-enhancements.md +++ b/docs/topics/browser-enhancements.md @@ -1,12 +1,12 @@ # Browser enhancements -> "There are two noncontroversial uses for overloaded POST. The first is to *simulate* HTTP's uniform interface for clients like web browsers that don't support PUT, PATCH or DELETE" +> "There are two noncontroversial uses for overloaded POST. The first is to *simulate* HTTP's uniform interface for clients like web browsers that don't support PUT or DELETE" > > — [RESTful Web Services][cite], Leonard Richardson & Sam Ruby. -## Browser based PUT, PATCH, DELETE, etc... +## Browser based PUT, DELETE, etc... -REST framework supports browser-based `PUT`, `PATCH`, `DELETE` and other methods, by +REST framework supports browser-based `PUT`, `DELETE` and other methods, by overloading `POST` requests using a hidden form field. Note that this is the same strategy as is used in [Ruby on Rails][rails]. @@ -51,7 +51,7 @@ the view. This is a more concise than using the `accept` override, but it also gives you less control. (For example you can't specify any media type parameters) -## Doesn't HTML5 support PUT, PATCH and DELETE forms? +## Doesn't HTML5 support PUT and DELETE forms? Nope. It was at one point intended to support `PUT` and `DELETE` forms, but was later [dropped from the spec][html5]. There remains -- cgit v1.2.3 From 661c8f9ad56a1f5f35e4a769ac44b668227b14e6 Mon Sep 17 00:00:00 2001 From: swistakm Date: Mon, 28 Jan 2013 13:05:52 +0100 Subject: fix mistake in docs --- docs/api-guide/authentication.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'docs') diff --git a/docs/api-guide/authentication.md b/docs/api-guide/authentication.md index da494746..59afc2b9 100644 --- a/docs/api-guide/authentication.md +++ b/docs/api-guide/authentication.md @@ -190,9 +190,9 @@ Typically the approach you should take is: * If authentication is not attempted, return `None`. Any other authentication schemes also in use will still be checked. * If authentication is attempted but fails, raise a `AuthenticationFailed` exception. An error response will be returned immediately, without checking any other authentication schemes. -You *may* also override the `.authentication_header(self, request)` method. If implemented, it should return a string that will be used as the value of the `WWW-Authenticate` header in a `HTTP 401 Unauthorized` response. +You *may* also override the `.authenticate_header(self, request)` method. If implemented, it should return a string that will be used as the value of the `WWW-Authenticate` header in a `HTTP 401 Unauthorized` response. -If the `.authentication_header()` method is not overridden, the authentication scheme will return `HTTP 403 Forbidden` responses when an unauthenticated request is denied access. +If the `.authenticate_header()` method is not overridden, the authentication scheme will return `HTTP 403 Forbidden` responses when an unauthenticated request is denied access. ## Example -- cgit v1.2.3 From 2f14d79f4aad89a2a1ebd1191d99bdada2274fe9 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Mon, 28 Jan 2013 11:43:41 +0000 Subject: Added @wronglink, for docs fixes in #592. 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 19a6397c..930cc056 100644 --- a/docs/topics/credits.md +++ b/docs/topics/credits.md @@ -97,6 +97,7 @@ The following people have helped make REST framework great. * Kevin Stone - [kevinastone] * Guglielmo Celata - [guglielmo] * Mike Tums - [mktums] +* Michael Elovskikh - [wronglink] Many thanks to everyone who's contributed to the project. @@ -229,3 +230,4 @@ You can also contact [@_tomchristie][twitter] directly on twitter. [kevinastone]: https://github.com/kevinastone [guglielmo]: https://github.com/guglielmo [mktums]: https://github.com/mktums +[wronglink]: https://github.com/wronglink -- cgit v1.2.3 From 94c4a54bf806aef7af6b5f8b5d996060f1daad0f Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Mon, 28 Jan 2013 12:23:18 +0000 Subject: Update release notes. --- docs/topics/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'docs') diff --git a/docs/topics/release-notes.md b/docs/topics/release-notes.md index 84b30d85..945d4018 100644 --- a/docs/topics/release-notes.md +++ b/docs/topics/release-notes.md @@ -26,6 +26,10 @@ You can determine your currently installed version using `pip freeze`: ## 2.1.x series +### Master + +* Fix styling on browsable API login. + ### 2.1.17 **Date**: 26th Jan 2013 -- cgit v1.2.3 From 141814585c72828f099a76c54bf2a5191833fc04 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Mon, 28 Jan 2013 12:58:22 +0000 Subject: Update release notes --- docs/topics/release-notes.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/topics/release-notes.md b/docs/topics/release-notes.md index 945d4018..a6de1188 100644 --- a/docs/topics/release-notes.md +++ b/docs/topics/release-notes.md @@ -28,7 +28,8 @@ You can determine your currently installed version using `pip freeze`: ### Master -* Fix styling on browsable API login. +* Bugfix: Fix styling on browsable API login. +* Bugfix: Ensure model field validation is still applied for ModelSerializer subclasses with an custom `.restore_object()` method. ### 2.1.17 -- cgit v1.2.3 From 54096a19fc096c884c57e7a06340bf295a9098fb Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Mon, 28 Jan 2013 21:08:53 +0000 Subject: Added @swistakm, for docs fix #625. 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 930cc056..7e0546c7 100644 --- a/docs/topics/credits.md +++ b/docs/topics/credits.md @@ -98,6 +98,7 @@ The following people have helped make REST framework great. * Guglielmo Celata - [guglielmo] * Mike Tums - [mktums] * Michael Elovskikh - [wronglink] +* Michał Jaworski - [swistakm] Many thanks to everyone who's contributed to the project. @@ -231,3 +232,4 @@ You can also contact [@_tomchristie][twitter] directly on twitter. [guglielmo]: https://github.com/guglielmo [mktums]: https://github.com/mktums [wronglink]: https://github.com/wronglink +[swistakm]: https://github.com/swistakm -- cgit v1.2.3 From 5f065153c31b586ca058deb8f6bd48303e3628e5 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Tue, 29 Jan 2013 09:10:37 +0000 Subject: Added @z4r. Thanks! For ensuring `django-jsonfield` compatibility, via #629.--- 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 7e0546c7..2aa2c715 100644 --- a/docs/topics/credits.md +++ b/docs/topics/credits.md @@ -99,6 +99,7 @@ The following people have helped make REST framework great. * Mike Tums - [mktums] * Michael Elovskikh - [wronglink] * Michał Jaworski - [swistakm] +* Andrea de Marco - [z4r] Many thanks to everyone who's contributed to the project. @@ -233,3 +234,4 @@ You can also contact [@_tomchristie][twitter] directly on twitter. [mktums]: https://github.com/mktums [wronglink]: https://github.com/wronglink [swistakm]: https://github.com/swistakm +[z4r]: https://github.com/z4r -- cgit v1.2.3 From 1929159db1b45ef28d1f7fdf0bea9d0867af13f3 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Tue, 29 Jan 2013 09:15:08 +0000 Subject: Docs tweaks. --- docs/api-guide/fields.md | 4 +++- docs/api-guide/serializers.md | 12 +++--------- 2 files changed, 6 insertions(+), 10 deletions(-) (limited to 'docs') diff --git a/docs/api-guide/fields.md b/docs/api-guide/fields.md index e43282ce..3f8a36e2 100644 --- a/docs/api-guide/fields.md +++ b/docs/api-guide/fields.md @@ -240,7 +240,9 @@ Signature and validation is the same as with `FileField`. --- **Note:** `FileFields` and `ImageFields` are only suitable for use with MultiPartParser, since e.g. json doesn't support file uploads. -Django's regular [FILE_UPLOAD_HANDLERS] are used for handling uploaded files. +Django's regular [FILE_UPLOAD_HANDLERS] are used for handling uploaded files. + +--- [cite]: https://docs.djangoproject.com/en/dev/ref/forms/api/#django.forms.Form.cleaned_data [FILE_UPLOAD_HANDLERS]: https://docs.djangoproject.com/en/dev/ref/settings/#std:setting-FILE_UPLOAD_HANDLERS diff --git a/docs/api-guide/serializers.md b/docs/api-guide/serializers.md index d98a602f..487502e9 100644 --- a/docs/api-guide/serializers.md +++ b/docs/api-guide/serializers.md @@ -190,18 +190,12 @@ By default field values are treated as mapping to an attribute on the object. I As an example, let's create a field that can be used represent the class name of the object being serialized: - class ClassNameField(serializers.WritableField): + class ClassNameField(serializers.Field): def field_to_native(self, obj, field_name): """ - Serialize the object's class name, not an attribute of the object. + Serialize the object's class name. """ - return obj.__class__.__name__ - - def field_from_native(self, data, field_name, into): - """ - We don't want to set anything when we revert this field. - """ - pass + return obj.__class__ --- -- cgit v1.2.3 From ce914b03ed602f76a6b75eb76417a8711b6a8b5e Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Wed, 30 Jan 2013 12:42:51 +0000 Subject: Updated release notes. --- docs/topics/release-notes.md | 1 + 1 file changed, 1 insertion(+) (limited to 'docs') diff --git a/docs/topics/release-notes.md b/docs/topics/release-notes.md index a6de1188..70c915b7 100644 --- a/docs/topics/release-notes.md +++ b/docs/topics/release-notes.md @@ -29,6 +29,7 @@ You can determine your currently installed version using `pip freeze`: ### Master * Bugfix: Fix styling on browsable API login. +* Bugfix: Fix issue with deserializing empty to-many relations. * Bugfix: Ensure model field validation is still applied for ModelSerializer subclasses with an custom `.restore_object()` method. ### 2.1.17 -- cgit v1.2.3 From 8021bb5d5089955b171173e60dcc0968e13d29ea Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Wed, 30 Jan 2013 12:43:52 +0000 Subject: Added @fernandogrd for bugfix #632. 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 2aa2c715..a67a8169 100644 --- a/docs/topics/credits.md +++ b/docs/topics/credits.md @@ -100,6 +100,7 @@ The following people have helped make REST framework great. * Michael Elovskikh - [wronglink] * Michał Jaworski - [swistakm] * Andrea de Marco - [z4r] +* Fernando Rocha - [fernandogrd] Many thanks to everyone who's contributed to the project. @@ -235,3 +236,4 @@ You can also contact [@_tomchristie][twitter] directly on twitter. [wronglink]: https://github.com/wronglink [swistakm]: https://github.com/swistakm [z4r]: https://github.com/z4r +[fernandogrd]: https://github.com/fernandogrd -- cgit v1.2.3 From 00752dcd2a3647f2de2a259934753745597e3ade Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Fri, 1 Feb 2013 15:07:51 +0000 Subject: Py3k cleanup --- docs/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/index.md b/docs/index.md index 453a67b8..283ea069 100644 --- a/docs/index.md +++ b/docs/index.md @@ -33,7 +33,7 @@ There is also a sandbox API you can use for testing purposes, [available here][s REST framework requires the following: -* Python (2.6, 2.7) +* Python (2.6, 2.7, 3.2, 3.3) * Django (1.3, 1.4, 1.5) The following packages are optional: -- cgit v1.2.3 From b9f1fbb5d2a3a303968d3afbe72751219583b28b Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Fri, 1 Feb 2013 15:10:52 +0000 Subject: Added @xordoquy for the incredible py3k work! Commiter number 100! --- 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 a67a8169..ebca4491 100644 --- a/docs/topics/credits.md +++ b/docs/topics/credits.md @@ -101,6 +101,7 @@ The following people have helped make REST framework great. * Michał Jaworski - [swistakm] * Andrea de Marco - [z4r] * Fernando Rocha - [fernandogrd] +* Xavier Ordoquy - [xordoquy] Many thanks to everyone who's contributed to the project. @@ -237,3 +238,4 @@ You can also contact [@_tomchristie][twitter] directly on twitter. [swistakm]: https://github.com/swistakm [z4r]: https://github.com/z4r [fernandogrd]: https://github.com/fernandogrd +[xordoquy]: https://github.com/xordoquy -- cgit v1.2.3 From 280dfa4343fb7cf188f4573361bbec447b8ea7c2 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Mon, 4 Feb 2013 21:45:38 +0000 Subject: Remove 2.0 notice on main docs. --- docs/index.md | 6 ------ 1 file changed, 6 deletions(-) (limited to 'docs') diff --git a/docs/index.md b/docs/index.md index 283ea069..37e7cb3c 100644 --- a/docs/index.md +++ b/docs/index.md @@ -11,12 +11,6 @@ **A toolkit for building well-connected, self-describing Web APIs.** ---- - -**Note**: This documentation is for the 2.0 version of REST framework. If you are looking for earlier versions please see the [0.4.x branch][0.4] on GitHub. - ---- - Django REST framework is a lightweight library that makes it easy to build Web APIs. It is designed as a modular and easy to customize architecture, based on Django's class based views. Web APIs built using REST framework are fully self-describing and web browseable - a huge useability win for your developers. It also supports a wide range of media types, authentication and permission policies out of the box. -- cgit v1.2.3 From bdc97c561147130b59c8cd8cc6bc735eab8b223d Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Wed, 6 Feb 2013 08:52:21 +0000 Subject: 2.2 Release notes (wip) --- docs/topics/2.2-release-notes.md | 101 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 docs/topics/2.2-release-notes.md (limited to 'docs') diff --git a/docs/topics/2.2-release-notes.md b/docs/topics/2.2-release-notes.md new file mode 100644 index 00000000..32b3ad8c --- /dev/null +++ b/docs/topics/2.2-release-notes.md @@ -0,0 +1,101 @@ +# REST framework 2.2 release notes + +The 2.2 release represents an important point for REST framework, with the addition of Python 3 support, and the introduction of an official deprecation policy. + +## Python 3 support + +Thanks to some fantastic work from [Xavier Ordoquy][xordoquy], Django REST framework 2.2 now supports Python 3. You'll need to be running Django 1.5, and it's worth keeping in mind that Django's Python 3 support is currently [considered experimental][django-python-3]. + +Django 1.6's Python 3 support is expected to be officially labeled as 'production-ready'. + +If you want to start ensuring that your own projects are Python 3 ready, we can highly recommend Django's [Porting to Python 3][porting-python-3] documentation. + +## Deprecation policy + +We've now introduced an official deprecation policy, which is in line with [Django's deprecation policy][django-deprecation-policy]. This policy will make it easy for you to continue to track the latest, greatest version of REST framework. + +The timeline for deprecation works as follows: + +* Version 2.2 introduces some API changes as detailed in the release notes. It remains fully backwards compatible with 2.1, but will raise `PendingDeprecationWarning` warnings if you use bits API that are due to be deprecated. These warnings are silent by default, but can be explicitly enabled when you're ready to start migrating any required changes. For example if you start running your tests using `python -Wd manage.py test`, you'll be warned of any API changes you need to make. + +* Version 2.3 will escalate these warnings to `DeprecationWarning`, which is loud by default. + +* Version 2.4 will remove the deprecated bits of API entirely. + +Note that in line with Django's policy, any parts of the framework not mentioned in the documentation should generally be considered private API, and may be subject to change. + +## Community + +As of the 2.2 merge, we've also hit an impressive milestone. The number of committers listed in [the credits][credits], is now at over **one hundred individuals**. Each name on that list represents at least one merged pull request, however large or small. + +Our [mailing list][mailing-list] and #restframework IRC channel are also very active, and we've got a really impressive rate of development both on REST framework itself, and on third party packages such as the great [django-rest-framework-docs][django-rest-framework-docs] package from [Marc Gibbons][marcgibbons]. + +## API changes + +The 2.2 release makes a few changes to the serializer fields API, in order to make it more consistent, simple, and easier to use. + +### Cleaner to-many related fields + +The `ManyRelatedField()` style is being deprecated in favor of a new `RelatedField(many=True)` syntax. + +For example, if a user is associated with multiple questions, which we want to represent using a primary key relationship, we might use something like the following: + + class UserSerializer(serializers.HyperlinkedModelSerializer): + questions = serializers.PrimaryKeyRelatedField(many=True) + + class Meta: + fields = ('username', 'questions') + +The new syntax is cleaner and more obvious, and the change will also make the documentation cleaner, simplify the internal API, and make writing custom relational fields easier. + +The change also applies to serializers. If you have a nested serializer, you should start using `many=True` for to-many relationships. For example, a serializer representation of an Album that can contain many Tracks might look something like this: + + class TrackSerializer(serializer.ModelSerializer): + class Meta: + model = Track + fields = ('name', 'duration') + + class AlbumSerializer(serializer.ModelSerializer): + tracks = TrackSerializer(many=True) + + class Meta: + model = Album + fields = ('album_name', 'artist', 'tracks') + +Additionally, the change also applies when serializing or deserializing data. For example to serialize a queryset of models you should now use the `many=True` flag. + + serializer = SnippetSerializer(Snippet.objects.all(), many=True) + serializer.data + +This more explicit behavior on serializing and deserializing data [makes integration with non-ORM backends such as MongoDB easier][564], as instances to be serialized can include the `__iter__` method, without incorrectly triggering list-based serialization, or requiring workarounds. + +The implicit to-many behavior on serializers, and the `ManyRelatedField` style classes will continue to function, but will raise a `PendingDeprecationWarning`, which can be made visible using the `-Wd` flag. + +### Cleaner optional relationships + +Serializer relationships for nullable Foreign Keys will change from using the current `null=True` flag, to instead using `required=False`. + +This is in line both with the rest of the serializer fields API, and with Django's `Form` and `ModelForm` API. + +Using `required` throughout the serializers API means you won't need to consider if a particular field should take `blank` or `null` arguments instead of `required`, and also means there will be more consistent behavior for how fields are treated when they are not present in the incoming data. + +The `null=True` argument will continue to function, and will imply `required=False`, but will raise a `PendingDeprecationWarning`. + +### Cleaner CharField syntax + +The `CharField` API previously took an optional `blank=True` argument, which was intended to differentiate between null CharField input, and blank CharField input. + +In keeping with Django's CharField API, REST framework's `CharField` will only ever return the empty string, for missing or `None` inputs. The `blank` flag will no longer be in use, and you should instead just use the `required=` flag. + +The `blank` keyword argument will continue to function, but will raise a `PendingDeprecationWarning`. + +[xordoquy]: https://github.com/xordoquy +[django-python-3]: https://docs.djangoproject.com/en/dev/faq/install/#can-i-use-django-with-python-3 +[porting-python-3]: https://docs.djangoproject.com/en/dev/topics/python3/ +[django-deprecation-policy]: https://docs.djangoproject.com/en/dev/internals/release-process/#internal-release-deprecation-policy +[credits]: http://django-rest-framework.org/topics/credits.html +[mailing-list]: https://groups.google.com/forum/?fromgroups#!forum/django-rest-framework +[django-rest-framework-docs]: https://github.com/marcgibbons/django-rest-framework-docs +[marcgibbons]: https://github.com/marcgibbons/ +[issues]: https://github.com/tomchristie/django-rest-framework/issues +[564]: https://github.com/tomchristie/django-rest-framework/issues/564 -- cgit v1.2.3 From 4788c87b76782b828d4c504e8a5deab4e07ebcd4 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Wed, 6 Feb 2013 12:35:05 +0000 Subject: Fix mismatch between template blocks and docs. Fixes #639. --- docs/topics/browsable-api.md | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'docs') diff --git a/docs/topics/browsable-api.md b/docs/topics/browsable-api.md index 9fe82e69..5f80c4f9 100644 --- a/docs/topics/browsable-api.md +++ b/docs/topics/browsable-api.md @@ -35,23 +35,20 @@ A suitable replacement theme can be generated using Bootstrap's [Customize Tool] 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. +For more specific CSS tweaks, use the `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][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 `` * `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. +* `style` - CSS stylesheets for the page * `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. -- cgit v1.2.3 From 691a8f682dcd1e5e839ce36ac259f08ba9a2e216 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Wed, 6 Feb 2013 12:48:08 +0000 Subject: Note on turning off implicit many behavior. Refs #564. --- docs/topics/2.2-release-notes.md | 2 ++ 1 file changed, 2 insertions(+) (limited to 'docs') diff --git a/docs/topics/2.2-release-notes.md b/docs/topics/2.2-release-notes.md index 32b3ad8c..ab1ab0c5 100644 --- a/docs/topics/2.2-release-notes.md +++ b/docs/topics/2.2-release-notes.md @@ -71,6 +71,8 @@ This more explicit behavior on serializing and deserializing data [makes integra The implicit to-many behavior on serializers, and the `ManyRelatedField` style classes will continue to function, but will raise a `PendingDeprecationWarning`, which can be made visible using the `-Wd` flag. +**Note**: If you need to forcibly turn off the implict "`many=True` for `__iter__` objects" behavior, you can now do so by specifying `many=False`. This will become the default (instead of the current default of `None`) once the deprecation of the implicit behavior is finalised in version 2.4. + ### Cleaner optional relationships Serializer relationships for nullable Foreign Keys will change from using the current `null=True` flag, to instead using `required=False`. -- cgit v1.2.3 From cc2ec2bbf0aee53d360a81cf338361feca1e8f80 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Wed, 6 Feb 2013 12:57:59 +0000 Subject: Tweaks to release notes. --- docs/topics/2.2-release-notes.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/topics/2.2-release-notes.md b/docs/topics/2.2-release-notes.md index ab1ab0c5..be9c8ab0 100644 --- a/docs/topics/2.2-release-notes.md +++ b/docs/topics/2.2-release-notes.md @@ -77,6 +77,10 @@ The implicit to-many behavior on serializers, and the `ManyRelatedField` style c Serializer relationships for nullable Foreign Keys will change from using the current `null=True` flag, to instead using `required=False`. +For example, is a user account has an optional foreign key to a company, that you want to express using a hyperlink, you might use the following field in a `Serializer` class: + + current_company = serializers.HyperlinkedRelatedField(required=False) + This is in line both with the rest of the serializer fields API, and with Django's `Form` and `ModelForm` API. Using `required` throughout the serializers API means you won't need to consider if a particular field should take `blank` or `null` arguments instead of `required`, and also means there will be more consistent behavior for how fields are treated when they are not present in the incoming data. @@ -87,7 +91,9 @@ The `null=True` argument will continue to function, and will imply `required=Fal The `CharField` API previously took an optional `blank=True` argument, which was intended to differentiate between null CharField input, and blank CharField input. -In keeping with Django's CharField API, REST framework's `CharField` will only ever return the empty string, for missing or `None` inputs. The `blank` flag will no longer be in use, and you should instead just use the `required=` flag. +In keeping with Django's CharField API, REST framework's `CharField` will only ever return the empty string, for missing or `None` inputs. The `blank` flag will no longer be in use, and you should instead just use the `required=` flag. For example: + + extra_details = CharField(required=False) The `blank` keyword argument will continue to function, but will raise a `PendingDeprecationWarning`. -- cgit v1.2.3 From c18fb0d6953940f63cd8747a5ce543d31999996f Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Wed, 6 Feb 2013 21:28:03 +0000 Subject: Added a `post_save` hook. Closes #558. --- docs/api-guide/generic-views.md | 9 +++++++++ docs/topics/release-notes.md | 1 + 2 files changed, 10 insertions(+) (limited to 'docs') diff --git a/docs/api-guide/generic-views.md b/docs/api-guide/generic-views.md index 693e210d..20f1be63 100644 --- a/docs/api-guide/generic-views.md +++ b/docs/api-guide/generic-views.md @@ -131,6 +131,15 @@ Each of the generic views provided is built by combining one of the base views b Extends REST framework's `APIView` class, adding support for serialization of model instances and model querysets. +**Methods**: + +* `get_serializer_context(self)` - Returns a dictionary containing any extra context that should be supplied to the serializer. Defaults to including `'request'`, `'view'` and `'format'` keys. +* `get_serializer_class(self)` - Returns the class that should be used for the serializer. +* `get_serializer(self, instance=None, data=None, files=None, many=False, partial=False)` - Returns a serializer instance. +* `pre_save(self, obj)` - A hook that is called before saving an object. +* `post_save(self, obj, created=False)` - A hook that is called after saving an object. + + **Attributes**: * `model` - The model that should be used for this view. Used as a fallback for determining the serializer if `serializer_class` is not set, and as a fallback for determining the queryset if `queryset` is not set. Otherwise not required. diff --git a/docs/topics/release-notes.md b/docs/topics/release-notes.md index 70c915b7..d5f060e7 100644 --- a/docs/topics/release-notes.md +++ b/docs/topics/release-notes.md @@ -28,6 +28,7 @@ You can determine your currently installed version using `pip freeze`: ### Master +* Added a `post_save()` hook to the generic views. * Bugfix: Fix styling on browsable API login. * Bugfix: Fix issue with deserializing empty to-many relations. * Bugfix: Ensure model field validation is still applied for ModelSerializer subclasses with an custom `.restore_object()` method. -- cgit v1.2.3 From 670ac25b25a3c7fb54fca6aa9344b8250ab49edb Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Thu, 7 Feb 2013 12:57:40 +0000 Subject: Allow serializers to handle dicts as well as objects. Fixes #447. --- docs/topics/release-notes.md | 1 + 1 file changed, 1 insertion(+) (limited to 'docs') diff --git a/docs/topics/release-notes.md b/docs/topics/release-notes.md index d5f060e7..4317b83c 100644 --- a/docs/topics/release-notes.md +++ b/docs/topics/release-notes.md @@ -29,6 +29,7 @@ You can determine your currently installed version using `pip freeze`: ### Master * Added a `post_save()` hook to the generic views. +* Allow serializers to handle dicts as well as objects. * Bugfix: Fix styling on browsable API login. * Bugfix: Fix issue with deserializing empty to-many relations. * Bugfix: Ensure model field validation is still applied for ModelSerializer subclasses with an custom `.restore_object()` method. -- cgit v1.2.3 From 4dcc34ecae8d15e31158abfe3d3aab223851fd61 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Thu, 7 Feb 2013 13:16:17 +0000 Subject: More 2.2 release notes --- docs/topics/2.2-release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'docs') diff --git a/docs/topics/2.2-release-notes.md b/docs/topics/2.2-release-notes.md index be9c8ab0..4ed9f970 100644 --- a/docs/topics/2.2-release-notes.md +++ b/docs/topics/2.2-release-notes.md @@ -30,6 +30,10 @@ As of the 2.2 merge, we've also hit an impressive milestone. The number of comm Our [mailing list][mailing-list] and #restframework IRC channel are also very active, and we've got a really impressive rate of development both on REST framework itself, and on third party packages such as the great [django-rest-framework-docs][django-rest-framework-docs] package from [Marc Gibbons][marcgibbons]. +## Issue management + +All the design work that went into version 2 of Django REST framework has made keeping on top of issues much easier. We've been super-focused on keeping the [issues list][issues] strictly under control, and we've hit another important milestone. At the point of releasing 2.2 there are currently **no open 'bug' tickets**, and the plan is to keep it that way for as much of the time as possible. + ## API changes The 2.2 release makes a few changes to the serializer fields API, in order to make it more consistent, simple, and easier to use. -- cgit v1.2.3 From 47d6640ea5d3fe64507249c6a170f6e7f4ab9688 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Thu, 7 Feb 2013 21:07:33 +0000 Subject: Remove email --- docs/topics/credits.md | 1 - 1 file changed, 1 deletion(-) (limited to 'docs') diff --git a/docs/topics/credits.md b/docs/topics/credits.md index ebca4491..b84f1357 100644 --- a/docs/topics/credits.md +++ b/docs/topics/credits.md @@ -125,7 +125,6 @@ For usage questions please see the [REST framework discussion group][group]. You can also contact [@_tomchristie][twitter] directly on twitter. -[email]: mailto:tom@tomchristie.com [twitter]: http://twitter.com/_tomchristie [bootstrap]: http://twitter.github.com/bootstrap/ [markdown]: http://daringfireball.net/projects/markdown/ -- cgit v1.2.3 From 7ffb2435ca87676173e8c634401a9c871b1e2087 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Thu, 7 Feb 2013 21:23:10 +0000 Subject: Add link to djangorestframework-digestauth --- docs/api-guide/authentication.md | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'docs') diff --git a/docs/api-guide/authentication.md b/docs/api-guide/authentication.md index 59afc2b9..9c899f17 100644 --- a/docs/api-guide/authentication.md +++ b/docs/api-guide/authentication.md @@ -137,7 +137,8 @@ Unauthenticated responses that are denied permission will result in an `HTTP 401 **Note:** If you use `TokenAuthentication` in production you must ensure that your API is only available over `https` only. -======= +--- + If you want every user to have an automatically generated Token, you can simply catch the User's `post_save` signal. @receiver(post_save, sender=User) @@ -210,7 +211,16 @@ The following example will authenticate any incoming request as the user given b raise authenticate.AuthenticationFailed('No such user') return (user, None) - + +--- + +# Third party packages + +The following third party packages are also available. + +## Digest Authentication + +HTTP digest authentication is a widely implemented scheme that was intended to replace HTTP basic authentication, and which provides a simple encrypted authentication mechanism. [Juan Riaza][juanriaza] maintains the [djangorestframework-digestauth][djangorestframework-digestauth] package which provides HTTP digest authentication support for REST framework. [cite]: http://jacobian.org/writing/rest-worst-practices/ [http401]: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.2 @@ -221,3 +231,5 @@ The following example will authenticate any incoming request as the user given b [throttling]: throttling.md [csrf-ajax]: https://docs.djangoproject.com/en/dev/ref/contrib/csrf/#ajax [mod_wsgi_official]: http://code.google.com/p/modwsgi/wiki/ConfigurationDirectives#WSGIPassAuthorization +[juanriaza]: https://github.com/juanriaza +[djangorestframework-digestauth]: https://github.com/juanriaza/django-rest-framework-digestauth -- cgit v1.2.3 From 15c8fd96ef34cb48bd85f7f886c8c0db71c73cff Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Thu, 7 Feb 2013 23:11:12 +0000 Subject: Docs for related fields, with lots of examples. --- docs/api-guide/relations.md | 349 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 279 insertions(+), 70 deletions(-) (limited to 'docs') diff --git a/docs/api-guide/relations.md b/docs/api-guide/relations.md index 9f5a04b2..aedff96e 100644 --- a/docs/api-guide/relations.md +++ b/docs/api-guide/relations.md @@ -12,128 +12,337 @@ Relational fields are used to represent model relationships. They can be applie --- -**Note:** The relational fields are declared in `relations.py`, but by convention you should import them using `from rest_framework import serializers` and refer to fields as `serializers.`. +**Note:** The relational fields are declared in `relations.py`, but by convention you should import them from the `serializers` module, using `from rest_framework import serializers` and refer to fields as `serializers.`. --- -## RelatedField - -This field can be applied to any of the following: - -* A `ForeignKey` field. -* A `OneToOneField` field. -* A reverse OneToOne relationship -* Any other "to-one" relationship. - -By default `RelatedField` will represent the target of the field using it's `__unicode__` method. - -You can customize this behavior by subclassing `ManyRelatedField`, and overriding the `.to_native(self, value)` method. +# API Reference -## ManyRelatedField +In order to explain the various types of relational fields, we'll use a couple of simple models for our examples. Our models will be for music albums, and the tracks listed on each album. -This field can be applied to any of the following: - -* A `ManyToManyField` field. -* A reverse ManyToMany relationship. -* A reverse ForeignKey relationship -* Any other "to-many" relationship. - -By default `ManyRelatedField` will represent the targets of the field using their `__unicode__` method. + class Album(models.Model): + album_name = models.CharField(max_length=100) + artist = models.CharField(max_length=100) -For example, given the following models: + class Track(models.Model): + album = models.ForeignKey(Album, related_name='tracks') + order = models.IntegerField() + title = models.CharField(max_length=100) + duration = models.IntegerField() - class TaggedItem(models.Model): - """ - Tags arbitrary model instances using a generic relation. + class Meta: + unique_together = ('album', 'order') - See: https://docs.djangoproject.com/en/dev/ref/contrib/contenttypes/ - """ - tag = models.SlugField() - content_type = models.ForeignKey(ContentType) - object_id = models.PositiveIntegerField() - content_object = GenericForeignKey('content_type', 'object_id') - def __unicode__(self): - return self.tag - - - class Bookmark(models.Model): - """ - A bookmark consists of a URL, and 0 or more descriptive tags. - """ - url = models.URLField() - tags = GenericRelation(TaggedItem) + return '%d: %s' % (self.order, self.title) -And a model serializer defined like this: +## RelatedField - class BookmarkSerializer(serializers.ModelSerializer): - tags = serializers.ManyRelatedField() +`RelatedField` may be used to represent the target of the relationship using it's `__unicode__` method. +For example, the following serializer. + + class AlbumSerializer(serializer.ModelSerializer): + tracks = RelatedField(many=True) + class Meta: - model = Bookmark - exclude = ('id',) + fields = ('album_name', 'artist', 'tracks') -Then an example output format for a Bookmark instance would be: +Would serialize to the following representation. { - 'tags': [u'django', u'python'], - 'url': u'https://www.djangoproject.com/' + 'album_name': 'Things We Lost In The Fire', + 'artist': 'Low' + 'tracks': [ + '1: Sunflower', + '2: Whitetail', + '3: Dinosaur Act', + ... + ] } -## PrimaryKeyRelatedField -## ManyPrimaryKeyRelatedField +This field is read only. -`PrimaryKeyRelatedField` and `ManyPrimaryKeyRelatedField` will represent the target of the relationship using it's primary key. +## PrimaryKeyRelatedField -By default these fields are read-write, although you can change this behavior using the `read_only` flag. +`PrimaryKeyRelatedField` may be used to represent the target of the relationship using it's primary key. -**Arguments**: - -* `queryset` - By default `ModelSerializer` classes will use the default queryset for the relationship. `Serializer` classes must either set a queryset explicitly, or set `read_only=True`. -* `null` - If set to `True`, the field will accept values of `None` or the empty-string for nullable relationships. +For example, the following serializer: + + class AlbumSerializer(serializer.ModelSerializer): + tracks = PrimaryKeyRelatedField(many=True, read_only=True) + + class Meta: + fields = ('album_name', 'artist', 'tracks') -## SlugRelatedField -## ManySlugRelatedField +Would serialize to a representation like this: -`SlugRelatedField` and `ManySlugRelatedField` will represent the target of the relationship using a unique slug. + { + 'album_name': 'The Roots', + 'artist': 'Undun' + 'tracks': [ + 89, + 90, + 91, + ... + ] + } -By default these fields read-write, although you can change this behavior using the `read_only` flag. +By default this field is read-write, although you can change this behavior using the `read_only` flag. **Arguments**: -* `slug_field` - The field on the target that should be used to represent it. This should be a field that uniquely identifies any given instance. For example, `username`. * `queryset` - By default `ModelSerializer` classes will use the default queryset for the relationship. `Serializer` classes must either set a queryset explicitly, or set `read_only=True`. -* `null` - If set to `True`, the field will accept values of `None` or the empty-string for nullable relationships. +* `required` - If set to `False`, the field will accept values of `None` or the empty-string for nullable relationships. ## HyperlinkedRelatedField -## ManyHyperlinkedRelatedField -`HyperlinkedRelatedField` and `ManyHyperlinkedRelatedField` will represent the target of the relationship using a hyperlink. +`HyperlinkedRelatedField` may be used to represent the target of the relationship using a hyperlink. -By default, `HyperlinkedRelatedField` is read-write, although you can change this behavior using the `read_only` flag. +For example, the following serializer: + + class AlbumSerializer(serializer.ModelSerializer): + tracks = HyperlinkedRelatedField(many=True, read_only=True, + view_name='track-detail') + + class Meta: + fields = ('album_name', 'artist', 'tracks') + +Would serialize to a representation like this: + + { + 'album_name': 'Graceland', + 'artist': 'Paul Simon' + 'tracks': [ + 'http://www.example.com/api/tracks/45', + 'http://www.example.com/api/tracks/46', + 'http://www.example.com/api/tracks/47', + ... + ] + } + +By default this field is read-write, although you can change this behavior using the `read_only` flag. **Arguments**: * `view_name` - The view name that should be used as the target of the relationship. **required**. -* `format` - If using format suffixes, hyperlinked fields will use the same format suffix for the target unless overridden by using the `format` argument. +* `required` - If set to `False`, the field will accept values of `None` or the empty-string for nullable relationships. * `queryset` - By default `ModelSerializer` classes will use the default queryset for the relationship. `Serializer` classes must either set a queryset explicitly, or set `read_only=True`. * `slug_field` - The field on the target that should be used for the lookup. Default is `'slug'`. * `pk_url_kwarg` - The named url parameter for the pk field lookup. Default is `pk`. * `slug_url_kwarg` - The named url parameter for the slug field lookup. Default is to use the same value as given for `slug_field`. +* `format` - If using format suffixes, hyperlinked fields will use the same format suffix for the target unless overridden by using the `format` argument. + +## SlugRelatedField + +`SlugRelatedField` may be used to represent the target of the relationship using a field on the target. + +For example, the following serializer: + + class AlbumSerializer(serializer.ModelSerializer): + tracks = SlugRelatedField(many=True, read_only=True, slug_field='title') + + class Meta: + fields = ('album_name', 'artist', 'tracks') + +Would serialize to a representation like this: + + { + 'album_name': 'Dear John', + 'artist': 'Loney Dear' + 'tracks': [ + 'Airport Surroundings', + 'Everything Turns to You', + 'I Was Only Going Out', + ... + ] + } + +By default this field is read-write, although you can change this behavior using the `read_only` flag. + +When using `SlugRelatedField` as a read-write field, you will normally want to ensure that the slug field corresponds to a model field with `unique=True`. + +**Arguments**: + +* `slug_field` - The field on the target that should be used to represent it. This should be a field that uniquely identifies any given instance. For example, `username`. +* `queryset` - By default `ModelSerializer` classes will use the default queryset for the relationship. `Serializer` classes must either set a queryset explicitly, or set `read_only=True`. * `null` - If set to `True`, the field will accept values of `None` or the empty-string for nullable relationships. ## HyperLinkedIdentityField -This field can be applied as an identity relationship, such as the `'url'` field on a HyperlinkedModelSerializer. +This field can be applied as an identity relationship, such as the `'url'` field on a HyperlinkedModelSerializer. It can also be used for an attribute on the object. For example, the following serializer: + + class AlbumSerializer(serializers.HyperlinkedModelSerializer): + track_listing = HyperLinkedIdentityField(view_name='track-list') + + class Meta: + fields = ('album_name', 'artist', 'track_listing') + +Would serialize to a representation like this: + { + 'album_name': 'The Eraser', + 'artist': 'Thom Yorke' + 'track_listing': 'http://www.example.com/api/track_list/12', + } + This field is always read-only. **Arguments**: * `view_name` - The view name that should be used as the target of the relationship. **required**. -* `format` - If using format suffixes, hyperlinked fields will use the same format suffix for the target unless overridden by using the `format` argument. * `slug_field` - The field on the target that should be used for the lookup. Default is `'slug'`. * `pk_url_kwarg` - The named url parameter for the pk field lookup. Default is `pk`. * `slug_url_kwarg` - The named url parameter for the slug field lookup. Default is to use the same value as given for `slug_field`. +* `format` - If using format suffixes, hyperlinked fields will use the same format suffix for the target unless overridden by using the `format` argument. + +## Nested relationships + +Nested relationships can be expressed by using serializers as fields. For example: + + class TrackSerializer(serializer.ModelSerializer): + class Meta: + fields = ('order', 'title') + + class AlbumSerializer(serializer.ModelSerializer): + tracks = TrackSerializer(many=True) + + class Meta: + fields = ('album_name', 'artist', 'tracks') + +Note that nested relationships are currently read-only. For read-write relationships, you should use a flat relational style. + +## Custom relational fields + +To implement a custom relational field, you should override `RelatedField`, and implement the `.to_native(self, value)` method. This method takes the target of the field as the `value` argument, and should return the representation that should be used to serialize the target. + + class TrackListingField(serializers.RelatedField): + def to_native(self, value): + return 'Track %d: %s' % (value.ordering, value.name) + +If you want to implement a read-write relational field, you must also implement the `.from_native(self, data)` method, and add `read_only = False` to the class definition. + +# Further notes + +## Reverse relations + +Note that reverse relationships are not automatically generated by the `ModelSerializer` and `HyperlinkedModelSerializer` classes. To include a reverse relationship, you cannot simply add it to the fields list. + +**The following will not work:** + + class AlbumSerializer(serializer.ModelSerializer): + class Meta: + fields = ('tracks', ...) + +Instead, you must explicitly add it to the serializer. For example: + + class AlbumSerializer(serializer.ModelSerializer): + tracks = serializers.PrimaryKeyRelationship(many=True) + ... + +By default, the field will uses the same accessor as it's field name to retrieve the relationship, so in this example, `Album` instances would need to have the `tracks` attribute for this relationship to work. + +The best way to ensure this is typically to make sure that the relationship on the model definition has it's `related_name` argument properly set. For example: + + class Track(models.Model): + album = models.ForeignKey(Album, related_name='tracks') + ... + +Alternatively, you can use the `source` argument on the serializer field, to use a different accessor attribute than the field name. For example. + + class AlbumSerializer(serializer.ModelSerializer): + tracks = serializers.PrimaryKeyRelationship(many=True, source='track_set') + +See the Django documentation on [reverse relationships][reverse-relationships] for more details. + +## Generic relationships + +If you want to serialize a generic foreign key, you need to define a custom field, to determine explicitly how you want serialize the targets of the relationship. + +For example, given the following model for a tag, which has a generic relationship with other arbitrary models: + + class TaggedItem(models.Model): + """ + Tags arbitrary model instances using a generic relation. + + See: https://docs.djangoproject.com/en/dev/ref/contrib/contenttypes/ + """ + tag_name = models.SlugField() + content_type = models.ForeignKey(ContentType) + object_id = models.PositiveIntegerField() + tagged_object = GenericForeignKey('content_type', 'object_id') + + def __unicode__(self): + return self.tag + +And the following two models, which may be have associated tags: + + class Bookmark(models.Model): + """ + A bookmark consists of a URL, and 0 or more descriptive tags. + """ + url = models.URLField() + tags = GenericRelation(TaggedItem) + + + class Note(models.Model): + """ + A note consists of some text, and 0 or more descriptive tags. + """ + text = models.CharField(max_length=1000) + tags = GenericRelation(TaggedItem) + +We could define a custom field that could be used to serialize tagged instances, using the type of each instance to determine how it should be serialized. + + class TaggedObjectRelatedField(serializers.RelatedField): + """ + A custom field to use for the `tagged_object` generic relationship. + """ + + def to_native(self, value): + """ + Serialize tagged objects to a simple textual representation. + """ + if isinstance(value, Bookmark): + return 'Bookmark: ' + value.url + elif isinstance(value, Note): + return 'Note: ' + value.text + raise Exception('Unexpected type of tagged object') + +If you need the target of the relationship to have a nested representation, you can use the required serializers inside the `.to_native()` method: + + def to_native(self, value): + """ + Serialize bookmark instances using a bookmark serializer, + and note instances using a note serializer. + """ + if isinstance(value, Bookmark): + serializer = BookmarkSerializer(value) + elif isinstance(value, Note): + serializer = NoteSerializer(value) + else: + raise Exception('Unexpected type of tagged object') + + return serializer.data + +Note that reverse generic keys, expressed using the `GenericRelation` field, can be serialized using the regular relational field types, since the type of the target in the relationship is always known. + +For more information see [the Django documentation on generic relations][generic-relations]. + +--- + +## Deprecated relational fields + +The following classes have been deprecated, in favor of the `many=` syntax. +They continue to function, but their usage will raise a `PendingDeprecationWarning`, which is silent by default. +In the 2.3 release, this warning will be escalated to a `DeprecationWarning`. +In the 2.4 release, they will be removed entirely. + +* `ManyRelatedField` +* `ManyPrimaryKeyRelatedField` +* `ManyHyperlinkedRelatedField` +* `ManySlugRelatedField` [cite]: http://lwn.net/Articles/193245/ +[reverse-relationships]: https://docs.djangoproject.com/en/dev/topics/db/queries/#following-relationships-backward +[generic-relations]: https://docs.djangoproject.com/en/dev/ref/contrib/contenttypes/#id1 -- cgit v1.2.3 From fd57978cb757597b82b58df78c52dc98eaed875e Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Fri, 8 Feb 2013 09:01:45 +0000 Subject: Add missing `model =` to serializer classes in docs --- docs/api-guide/relations.md | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'docs') diff --git a/docs/api-guide/relations.md b/docs/api-guide/relations.md index aedff96e..c5da084b 100644 --- a/docs/api-guide/relations.md +++ b/docs/api-guide/relations.md @@ -46,6 +46,7 @@ For example, the following serializer. tracks = RelatedField(many=True) class Meta: + model = Album fields = ('album_name', 'artist', 'tracks') Would serialize to the following representation. @@ -73,6 +74,7 @@ For example, the following serializer: tracks = PrimaryKeyRelatedField(many=True, read_only=True) class Meta: + model = Album fields = ('album_name', 'artist', 'tracks') Would serialize to a representation like this: @@ -106,6 +108,7 @@ For example, the following serializer: view_name='track-detail') class Meta: + model = Album fields = ('album_name', 'artist', 'tracks') Would serialize to a representation like this: @@ -143,6 +146,7 @@ For example, the following serializer: tracks = SlugRelatedField(many=True, read_only=True, slug_field='title') class Meta: + model = Album fields = ('album_name', 'artist', 'tracks') Would serialize to a representation like this: @@ -176,6 +180,7 @@ This field can be applied as an identity relationship, such as the `'url'` field track_listing = HyperLinkedIdentityField(view_name='track-list') class Meta: + model = Album fields = ('album_name', 'artist', 'track_listing') Would serialize to a representation like this: @@ -208,6 +213,7 @@ Nested relationships can be expressed by using serializers as fields. For examp tracks = TrackSerializer(many=True) class Meta: + model = Album fields = ('album_name', 'artist', 'tracks') Note that nested relationships are currently read-only. For read-write relationships, you should use a flat relational style. -- cgit v1.2.3 From 0997ce9fc20cd9ff8e63246c3892d28b411bf857 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Sun, 10 Feb 2013 16:44:32 +0000 Subject: Improve relations documentation. --- docs/api-guide/relations.md | 93 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 79 insertions(+), 14 deletions(-) (limited to 'docs') diff --git a/docs/api-guide/relations.md b/docs/api-guide/relations.md index c5da084b..25fca475 100644 --- a/docs/api-guide/relations.md +++ b/docs/api-guide/relations.md @@ -32,6 +32,7 @@ In order to explain the various types of relational fields, we'll use a couple o class Meta: unique_together = ('album', 'order') + order_by = 'order' def __unicode__(self): return '%d: %s' % (self.order, self.title) @@ -64,6 +65,10 @@ Would serialize to the following representation. This field is read only. +**Arguments**: + +* `many` - If applied to a to-many relationship, you should set this argument to `True`. + ## PrimaryKeyRelatedField `PrimaryKeyRelatedField` may be used to represent the target of the relationship using it's primary key. @@ -94,8 +99,9 @@ By default this field is read-write, although you can change this behavior using **Arguments**: -* `queryset` - By default `ModelSerializer` classes will use the default queryset for the relationship. `Serializer` classes must either set a queryset explicitly, or set `read_only=True`. +* `many` - If applied to a to-many relationship, you should set this argument to `True`. * `required` - If set to `False`, the field will accept values of `None` or the empty-string for nullable relationships. +* `queryset` - By default `ModelSerializer` classes will use the default queryset for the relationship. `Serializer` classes must either set a queryset explicitly, or set `read_only=True`. ## HyperlinkedRelatedField @@ -129,6 +135,7 @@ By default this field is read-write, although you can change this behavior using **Arguments**: * `view_name` - The view name that should be used as the target of the relationship. **required**. +* `many` - If applied to a to-many relationship, you should set this argument to `True`. * `required` - If set to `False`, the field will accept values of `None` or the empty-string for nullable relationships. * `queryset` - By default `ModelSerializer` classes will use the default queryset for the relationship. `Serializer` classes must either set a queryset explicitly, or set `read_only=True`. * `slug_field` - The field on the target that should be used for the lookup. Default is `'slug'`. @@ -168,16 +175,17 @@ When using `SlugRelatedField` as a read-write field, you will normally want to e **Arguments**: -* `slug_field` - The field on the target that should be used to represent it. This should be a field that uniquely identifies any given instance. For example, `username`. +* `slug_field` - The field on the target that should be used to represent it. This should be a field that uniquely identifies any given instance. For example, `username`. **required** +* `many` - If applied to a to-many relationship, you should set this argument to `True`. +* `required` - If set to `False`, the field will accept values of `None` or the empty-string for nullable relationships. * `queryset` - By default `ModelSerializer` classes will use the default queryset for the relationship. `Serializer` classes must either set a queryset explicitly, or set `read_only=True`. -* `null` - If set to `True`, the field will accept values of `None` or the empty-string for nullable relationships. -## HyperLinkedIdentityField +## HyperlinkedIdentityField This field can be applied as an identity relationship, such as the `'url'` field on a HyperlinkedModelSerializer. It can also be used for an attribute on the object. For example, the following serializer: class AlbumSerializer(serializers.HyperlinkedModelSerializer): - track_listing = HyperLinkedIdentityField(view_name='track-list') + track_listing = HyperlinkedIdentityField(view_name='track-list') class Meta: model = Album @@ -201,12 +209,23 @@ This field is always read-only. * `slug_url_kwarg` - The named url parameter for the slug field lookup. Default is to use the same value as given for `slug_field`. * `format` - If using format suffixes, hyperlinked fields will use the same format suffix for the target unless overridden by using the `format` argument. -## Nested relationships +--- + +# Nested relationships + +Nested relationships can be expressed by using serializers as fields. + +If the field is used to represent a to-many relationship, you should add the `many=True` flag to the serializer field. + +Note that nested relationships are currently read-only. For read-write relationships, you should use a flat relational style. + +## Example -Nested relationships can be expressed by using serializers as fields. For example: +For example, the following serializer: class TrackSerializer(serializer.ModelSerializer): class Meta: + model = Track fields = ('order', 'title') class AlbumSerializer(serializer.ModelSerializer): @@ -216,17 +235,57 @@ Nested relationships can be expressed by using serializers as fields. For examp model = Album fields = ('album_name', 'artist', 'tracks') -Note that nested relationships are currently read-only. For read-write relationships, you should use a flat relational style. +Would serialize to a nested representation like this: -## Custom relational fields + { + 'album_name': 'The Grey Album', + 'artist': 'Danger Mouse' + 'tracks': [ + {'order': 1, 'title': 'Public Service Annoucement'}, + {'order': 2, 'title': 'What More Can I Say'}, + {'order': 3, 'title': 'Encore'}, + ... + ], + } + +# Custom relational fields To implement a custom relational field, you should override `RelatedField`, and implement the `.to_native(self, value)` method. This method takes the target of the field as the `value` argument, and should return the representation that should be used to serialize the target. +If you want to implement a read-write relational field, you must also implement the `.from_native(self, data)` method, and add `read_only = False` to the class definition. + +## Example + +For, example, we could define a relational field, to serialize a track to a custom string representation, using it's ordering, title, and duration. + + import time + class TrackListingField(serializers.RelatedField): def to_native(self, value): - return 'Track %d: %s' % (value.ordering, value.name) + duration = time.strftime('%M:%S', time.gmtime(value.duration)) + return 'Track %d: %s (%s)' % (value.order, value.name, duration) -If you want to implement a read-write relational field, you must also implement the `.from_native(self, data)` method, and add `read_only = False` to the class definition. + class AlbumSerializer(serializer.ModelSerializer): + tracks = TrackListingField(many=True) + + class Meta: + model = Album + fields = ('album_name', 'artist', 'tracks') + +This custom field would then serialize to the following representation. + + { + 'album_name': 'Sometimes I Wish We Were an Eagle', + 'artist': 'Bill Callahan' + 'tracks': [ + 'Track 1: Jim Cain (04:39)', + 'Track 2: Eid Ma Clack Shaw (04:19)', + 'Track 3: The Wind and the Dove (04:34)', + ... + ] + } + +--- # Further notes @@ -337,18 +396,24 @@ For more information see [the Django documentation on generic relations][generic --- -## Deprecated relational fields +## Deprecated APIs The following classes have been deprecated, in favor of the `many=` syntax. They continue to function, but their usage will raise a `PendingDeprecationWarning`, which is silent by default. -In the 2.3 release, this warning will be escalated to a `DeprecationWarning`. -In the 2.4 release, they will be removed entirely. * `ManyRelatedField` * `ManyPrimaryKeyRelatedField` * `ManyHyperlinkedRelatedField` * `ManySlugRelatedField` +The `null=` flag has been deprecated in favor of the `required=` flag. It will continue to function, but will raise a `PendingDeprecationWarning`. + +In the 2.3 release, these warnings will be escalated to a `DeprecationWarning`, which is loud by default. +In the 2.4 release, these parts of the API will be removed entirely. + +For more details see the [2.2 release announcement][2.2-announcement]. + [cite]: http://lwn.net/Articles/193245/ [reverse-relationships]: https://docs.djangoproject.com/en/dev/topics/db/queries/#following-relationships-backward [generic-relations]: https://docs.djangoproject.com/en/dev/ref/contrib/contenttypes/#id1 +[2.2-announcement]: ../topics/2.2-announcement.md -- cgit v1.2.3 From 84a1896b7de5c2e3fc5f564027e5fccd7b2447f9 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Sun, 10 Feb 2013 16:44:45 +0000 Subject: Change URL of 2.2 announcement --- docs/topics/2.2-announcement.md | 113 +++++++++++++++++++++++++++++++++++++++ docs/topics/2.2-release-notes.md | 113 --------------------------------------- 2 files changed, 113 insertions(+), 113 deletions(-) create mode 100644 docs/topics/2.2-announcement.md delete mode 100644 docs/topics/2.2-release-notes.md (limited to 'docs') diff --git a/docs/topics/2.2-announcement.md b/docs/topics/2.2-announcement.md new file mode 100644 index 00000000..4ed9f970 --- /dev/null +++ b/docs/topics/2.2-announcement.md @@ -0,0 +1,113 @@ +# REST framework 2.2 release notes + +The 2.2 release represents an important point for REST framework, with the addition of Python 3 support, and the introduction of an official deprecation policy. + +## Python 3 support + +Thanks to some fantastic work from [Xavier Ordoquy][xordoquy], Django REST framework 2.2 now supports Python 3. You'll need to be running Django 1.5, and it's worth keeping in mind that Django's Python 3 support is currently [considered experimental][django-python-3]. + +Django 1.6's Python 3 support is expected to be officially labeled as 'production-ready'. + +If you want to start ensuring that your own projects are Python 3 ready, we can highly recommend Django's [Porting to Python 3][porting-python-3] documentation. + +## Deprecation policy + +We've now introduced an official deprecation policy, which is in line with [Django's deprecation policy][django-deprecation-policy]. This policy will make it easy for you to continue to track the latest, greatest version of REST framework. + +The timeline for deprecation works as follows: + +* Version 2.2 introduces some API changes as detailed in the release notes. It remains fully backwards compatible with 2.1, but will raise `PendingDeprecationWarning` warnings if you use bits API that are due to be deprecated. These warnings are silent by default, but can be explicitly enabled when you're ready to start migrating any required changes. For example if you start running your tests using `python -Wd manage.py test`, you'll be warned of any API changes you need to make. + +* Version 2.3 will escalate these warnings to `DeprecationWarning`, which is loud by default. + +* Version 2.4 will remove the deprecated bits of API entirely. + +Note that in line with Django's policy, any parts of the framework not mentioned in the documentation should generally be considered private API, and may be subject to change. + +## Community + +As of the 2.2 merge, we've also hit an impressive milestone. The number of committers listed in [the credits][credits], is now at over **one hundred individuals**. Each name on that list represents at least one merged pull request, however large or small. + +Our [mailing list][mailing-list] and #restframework IRC channel are also very active, and we've got a really impressive rate of development both on REST framework itself, and on third party packages such as the great [django-rest-framework-docs][django-rest-framework-docs] package from [Marc Gibbons][marcgibbons]. + +## Issue management + +All the design work that went into version 2 of Django REST framework has made keeping on top of issues much easier. We've been super-focused on keeping the [issues list][issues] strictly under control, and we've hit another important milestone. At the point of releasing 2.2 there are currently **no open 'bug' tickets**, and the plan is to keep it that way for as much of the time as possible. + +## API changes + +The 2.2 release makes a few changes to the serializer fields API, in order to make it more consistent, simple, and easier to use. + +### Cleaner to-many related fields + +The `ManyRelatedField()` style is being deprecated in favor of a new `RelatedField(many=True)` syntax. + +For example, if a user is associated with multiple questions, which we want to represent using a primary key relationship, we might use something like the following: + + class UserSerializer(serializers.HyperlinkedModelSerializer): + questions = serializers.PrimaryKeyRelatedField(many=True) + + class Meta: + fields = ('username', 'questions') + +The new syntax is cleaner and more obvious, and the change will also make the documentation cleaner, simplify the internal API, and make writing custom relational fields easier. + +The change also applies to serializers. If you have a nested serializer, you should start using `many=True` for to-many relationships. For example, a serializer representation of an Album that can contain many Tracks might look something like this: + + class TrackSerializer(serializer.ModelSerializer): + class Meta: + model = Track + fields = ('name', 'duration') + + class AlbumSerializer(serializer.ModelSerializer): + tracks = TrackSerializer(many=True) + + class Meta: + model = Album + fields = ('album_name', 'artist', 'tracks') + +Additionally, the change also applies when serializing or deserializing data. For example to serialize a queryset of models you should now use the `many=True` flag. + + serializer = SnippetSerializer(Snippet.objects.all(), many=True) + serializer.data + +This more explicit behavior on serializing and deserializing data [makes integration with non-ORM backends such as MongoDB easier][564], as instances to be serialized can include the `__iter__` method, without incorrectly triggering list-based serialization, or requiring workarounds. + +The implicit to-many behavior on serializers, and the `ManyRelatedField` style classes will continue to function, but will raise a `PendingDeprecationWarning`, which can be made visible using the `-Wd` flag. + +**Note**: If you need to forcibly turn off the implict "`many=True` for `__iter__` objects" behavior, you can now do so by specifying `many=False`. This will become the default (instead of the current default of `None`) once the deprecation of the implicit behavior is finalised in version 2.4. + +### Cleaner optional relationships + +Serializer relationships for nullable Foreign Keys will change from using the current `null=True` flag, to instead using `required=False`. + +For example, is a user account has an optional foreign key to a company, that you want to express using a hyperlink, you might use the following field in a `Serializer` class: + + current_company = serializers.HyperlinkedRelatedField(required=False) + +This is in line both with the rest of the serializer fields API, and with Django's `Form` and `ModelForm` API. + +Using `required` throughout the serializers API means you won't need to consider if a particular field should take `blank` or `null` arguments instead of `required`, and also means there will be more consistent behavior for how fields are treated when they are not present in the incoming data. + +The `null=True` argument will continue to function, and will imply `required=False`, but will raise a `PendingDeprecationWarning`. + +### Cleaner CharField syntax + +The `CharField` API previously took an optional `blank=True` argument, which was intended to differentiate between null CharField input, and blank CharField input. + +In keeping with Django's CharField API, REST framework's `CharField` will only ever return the empty string, for missing or `None` inputs. The `blank` flag will no longer be in use, and you should instead just use the `required=` flag. For example: + + extra_details = CharField(required=False) + +The `blank` keyword argument will continue to function, but will raise a `PendingDeprecationWarning`. + +[xordoquy]: https://github.com/xordoquy +[django-python-3]: https://docs.djangoproject.com/en/dev/faq/install/#can-i-use-django-with-python-3 +[porting-python-3]: https://docs.djangoproject.com/en/dev/topics/python3/ +[django-deprecation-policy]: https://docs.djangoproject.com/en/dev/internals/release-process/#internal-release-deprecation-policy +[credits]: http://django-rest-framework.org/topics/credits.html +[mailing-list]: https://groups.google.com/forum/?fromgroups#!forum/django-rest-framework +[django-rest-framework-docs]: https://github.com/marcgibbons/django-rest-framework-docs +[marcgibbons]: https://github.com/marcgibbons/ +[issues]: https://github.com/tomchristie/django-rest-framework/issues +[564]: https://github.com/tomchristie/django-rest-framework/issues/564 diff --git a/docs/topics/2.2-release-notes.md b/docs/topics/2.2-release-notes.md deleted file mode 100644 index 4ed9f970..00000000 --- a/docs/topics/2.2-release-notes.md +++ /dev/null @@ -1,113 +0,0 @@ -# REST framework 2.2 release notes - -The 2.2 release represents an important point for REST framework, with the addition of Python 3 support, and the introduction of an official deprecation policy. - -## Python 3 support - -Thanks to some fantastic work from [Xavier Ordoquy][xordoquy], Django REST framework 2.2 now supports Python 3. You'll need to be running Django 1.5, and it's worth keeping in mind that Django's Python 3 support is currently [considered experimental][django-python-3]. - -Django 1.6's Python 3 support is expected to be officially labeled as 'production-ready'. - -If you want to start ensuring that your own projects are Python 3 ready, we can highly recommend Django's [Porting to Python 3][porting-python-3] documentation. - -## Deprecation policy - -We've now introduced an official deprecation policy, which is in line with [Django's deprecation policy][django-deprecation-policy]. This policy will make it easy for you to continue to track the latest, greatest version of REST framework. - -The timeline for deprecation works as follows: - -* Version 2.2 introduces some API changes as detailed in the release notes. It remains fully backwards compatible with 2.1, but will raise `PendingDeprecationWarning` warnings if you use bits API that are due to be deprecated. These warnings are silent by default, but can be explicitly enabled when you're ready to start migrating any required changes. For example if you start running your tests using `python -Wd manage.py test`, you'll be warned of any API changes you need to make. - -* Version 2.3 will escalate these warnings to `DeprecationWarning`, which is loud by default. - -* Version 2.4 will remove the deprecated bits of API entirely. - -Note that in line with Django's policy, any parts of the framework not mentioned in the documentation should generally be considered private API, and may be subject to change. - -## Community - -As of the 2.2 merge, we've also hit an impressive milestone. The number of committers listed in [the credits][credits], is now at over **one hundred individuals**. Each name on that list represents at least one merged pull request, however large or small. - -Our [mailing list][mailing-list] and #restframework IRC channel are also very active, and we've got a really impressive rate of development both on REST framework itself, and on third party packages such as the great [django-rest-framework-docs][django-rest-framework-docs] package from [Marc Gibbons][marcgibbons]. - -## Issue management - -All the design work that went into version 2 of Django REST framework has made keeping on top of issues much easier. We've been super-focused on keeping the [issues list][issues] strictly under control, and we've hit another important milestone. At the point of releasing 2.2 there are currently **no open 'bug' tickets**, and the plan is to keep it that way for as much of the time as possible. - -## API changes - -The 2.2 release makes a few changes to the serializer fields API, in order to make it more consistent, simple, and easier to use. - -### Cleaner to-many related fields - -The `ManyRelatedField()` style is being deprecated in favor of a new `RelatedField(many=True)` syntax. - -For example, if a user is associated with multiple questions, which we want to represent using a primary key relationship, we might use something like the following: - - class UserSerializer(serializers.HyperlinkedModelSerializer): - questions = serializers.PrimaryKeyRelatedField(many=True) - - class Meta: - fields = ('username', 'questions') - -The new syntax is cleaner and more obvious, and the change will also make the documentation cleaner, simplify the internal API, and make writing custom relational fields easier. - -The change also applies to serializers. If you have a nested serializer, you should start using `many=True` for to-many relationships. For example, a serializer representation of an Album that can contain many Tracks might look something like this: - - class TrackSerializer(serializer.ModelSerializer): - class Meta: - model = Track - fields = ('name', 'duration') - - class AlbumSerializer(serializer.ModelSerializer): - tracks = TrackSerializer(many=True) - - class Meta: - model = Album - fields = ('album_name', 'artist', 'tracks') - -Additionally, the change also applies when serializing or deserializing data. For example to serialize a queryset of models you should now use the `many=True` flag. - - serializer = SnippetSerializer(Snippet.objects.all(), many=True) - serializer.data - -This more explicit behavior on serializing and deserializing data [makes integration with non-ORM backends such as MongoDB easier][564], as instances to be serialized can include the `__iter__` method, without incorrectly triggering list-based serialization, or requiring workarounds. - -The implicit to-many behavior on serializers, and the `ManyRelatedField` style classes will continue to function, but will raise a `PendingDeprecationWarning`, which can be made visible using the `-Wd` flag. - -**Note**: If you need to forcibly turn off the implict "`many=True` for `__iter__` objects" behavior, you can now do so by specifying `many=False`. This will become the default (instead of the current default of `None`) once the deprecation of the implicit behavior is finalised in version 2.4. - -### Cleaner optional relationships - -Serializer relationships for nullable Foreign Keys will change from using the current `null=True` flag, to instead using `required=False`. - -For example, is a user account has an optional foreign key to a company, that you want to express using a hyperlink, you might use the following field in a `Serializer` class: - - current_company = serializers.HyperlinkedRelatedField(required=False) - -This is in line both with the rest of the serializer fields API, and with Django's `Form` and `ModelForm` API. - -Using `required` throughout the serializers API means you won't need to consider if a particular field should take `blank` or `null` arguments instead of `required`, and also means there will be more consistent behavior for how fields are treated when they are not present in the incoming data. - -The `null=True` argument will continue to function, and will imply `required=False`, but will raise a `PendingDeprecationWarning`. - -### Cleaner CharField syntax - -The `CharField` API previously took an optional `blank=True` argument, which was intended to differentiate between null CharField input, and blank CharField input. - -In keeping with Django's CharField API, REST framework's `CharField` will only ever return the empty string, for missing or `None` inputs. The `blank` flag will no longer be in use, and you should instead just use the `required=` flag. For example: - - extra_details = CharField(required=False) - -The `blank` keyword argument will continue to function, but will raise a `PendingDeprecationWarning`. - -[xordoquy]: https://github.com/xordoquy -[django-python-3]: https://docs.djangoproject.com/en/dev/faq/install/#can-i-use-django-with-python-3 -[porting-python-3]: https://docs.djangoproject.com/en/dev/topics/python3/ -[django-deprecation-policy]: https://docs.djangoproject.com/en/dev/internals/release-process/#internal-release-deprecation-policy -[credits]: http://django-rest-framework.org/topics/credits.html -[mailing-list]: https://groups.google.com/forum/?fromgroups#!forum/django-rest-framework -[django-rest-framework-docs]: https://github.com/marcgibbons/django-rest-framework-docs -[marcgibbons]: https://github.com/marcgibbons/ -[issues]: https://github.com/tomchristie/django-rest-framework/issues -[564]: https://github.com/tomchristie/django-rest-framework/issues/564 -- cgit v1.2.3 From 09b01887f234be55c14943028330f569823b2369 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Mon, 11 Feb 2013 12:47:56 +0000 Subject: New style object-level permission checks --- docs/api-guide/permissions.md | 39 +++++++++++++++++++++-- docs/tutorial/4-authentication-and-permissions.md | 6 +--- 2 files changed, 37 insertions(+), 8 deletions(-) (limited to 'docs') diff --git a/docs/api-guide/permissions.md b/docs/api-guide/permissions.md index 1814b811..5cb3ec3c 100644 --- a/docs/api-guide/permissions.md +++ b/docs/api-guide/permissions.md @@ -106,22 +106,55 @@ The `DjangoModelPermissions` class also supports object-level permissions. Thir # Custom permissions -To implement a custom permission, override `BasePermission` and implement the `.has_permission(self, request, view, obj=None)` method. +To implement a custom permission, override `BasePermission` and implement either, or both, of the `.has_permission(self, request, view)` and `.has_object_permission(self, request, view, obj)` methods. -The method should return `True` if the request should be granted access, and `False` otherwise. +The methods should return `True` if the request should be granted access, and `False` otherwise. -## Example +--- + +**Note**: In versions 2.0 and 2.1, the signature for the permission checks always included an optional `obj` parameter, like so: `.has_permission(self, request, view, obj=None)`. The method would be called twice, first for the global permission checks, with no object supplied, and second for the object-level check when required. + +As of version 2.2 this signature has now been replaced with two seperate method calls, which is more explict, and obvious. The old style signature continues to work, but it's use will result in a `PendingDeprecationWarning`, which is silent by default. In 2.3 this will be escalated to a `DeprecationWarning`, and in 2.4 the old-style signature will be removed. + +For more details see the [2.2 release announcement][2.2-announcement]. + +--- + +## Examples The following is an example of a permission class that checks the incoming request's IP address against a blacklist, and denies the request if the IP has been blacklisted. class BlacklistPermission(permissions.BasePermission): + """ + Global permission check for blacklisted IPs. + """ + def has_permission(self, request, view, obj=None): ip_addr = request.META['REMOTE_ADDR'] blacklisted = Blacklist.objects.filter(ip_addr=ip_addr).exists() return not blacklisted +As well as global permissions, that are run against all incoming requests, you can also create object-level permissions, that are only run against operations that affect a particular object instance. For example: + + class IsOwnerOrReadOnly(permissions.BasePermission): + """ + Object-level permission to only allow owners of an object to edit it. + """ + + def has_object_permission(self, request, view, obj): + # Read permissions are allowed to any request, + # so we'll always allow GET, HEAD or OPTIONS requests. + if request.method in permissions.SAFE_METHODS: + return True + + # Instance must have an attribute named `owner`. + return obj.owner == request.user + +Note that the generic views will check the appropriate object level permissions, but if you're writing your own custom views, you'll need to make sure you check the object level permission checks yourself, by calling `self.has_object_permission(request, obj)` from the view. + [cite]: https://developer.apple.com/library/mac/#documentation/security/Conceptual/AuthenticationAndAuthorizationGuide/Authorization/Authorization.html [authentication]: authentication.md [throttling]: throttling.md [contribauth]: https://docs.djangoproject.com/en/1.0/topics/auth/#permissions [guardian]: https://github.com/lukaszb/django-guardian +[2.2-announcement]: ../topics/2.2-announcement.md diff --git a/docs/tutorial/4-authentication-and-permissions.md b/docs/tutorial/4-authentication-and-permissions.md index e9e5246a..979421ea 100644 --- a/docs/tutorial/4-authentication-and-permissions.md +++ b/docs/tutorial/4-authentication-and-permissions.md @@ -161,11 +161,7 @@ In the snippets app, create a new file, `permissions.py` Custom permission to only allow owners of an object to edit it. """ - def has_permission(self, request, view, obj=None): - # Skip the check unless this is an object-level test - if obj is None: - return True - + def has_object_permission(self, request, view, obj): # Read permissions are allowed to any request, # so we'll always allow GET, HEAD or OPTIONS requests. if request.method in permissions.SAFE_METHODS: -- cgit v1.2.3 From f5a0275547ad264c8a9b9aa2a45cc461723a4f11 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Mon, 11 Feb 2013 13:02:20 +0000 Subject: Tidy up internal view permission checking logic. Also document correctly - these methods are now public and will fall under the deprecation policy from now on. --- docs/api-guide/permissions.md | 2 +- docs/api-guide/views.md | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'docs') diff --git a/docs/api-guide/permissions.md b/docs/api-guide/permissions.md index 5cb3ec3c..4845ac88 100644 --- a/docs/api-guide/permissions.md +++ b/docs/api-guide/permissions.md @@ -150,7 +150,7 @@ As well as global permissions, that are run against all incoming requests, you c # Instance must have an attribute named `owner`. return obj.owner == request.user -Note that the generic views will check the appropriate object level permissions, but if you're writing your own custom views, you'll need to make sure you check the object level permission checks yourself, by calling `self.has_object_permission(request, obj)` from the view. +Note that the generic views will check the appropriate object level permissions, but if you're writing your own custom views, you'll need to make sure you check the object level permission checks yourself. You can do so by calling `self.check_object_permissions(request, obj)` from the view once you have the object instance. This call will raise an appropriate `APIException` if any object-level permission checks fail, and will otherwise simply return. [cite]: https://developer.apple.com/library/mac/#documentation/security/Conceptual/AuthenticationAndAuthorizationGuide/Authorization/Authorization.html [authentication]: authentication.md diff --git a/docs/api-guide/views.md b/docs/api-guide/views.md index 574020f9..8b26b3e3 100644 --- a/docs/api-guide/views.md +++ b/docs/api-guide/views.md @@ -76,11 +76,11 @@ The following methods are used by REST framework to instantiate the various plug The following methods are called before dispatching to the handler method. -### .check_permissions(...) +### .check_permissions(self, request) -### .check_throttles(...) +### .check_throttles(self, request) -### .perform_content_negotiation(...) +### .perform_content_negotiation(self, request, force=False) ## Dispatch methods -- cgit v1.2.3 From 55fdac4176ac6629481a8cca8dd2463da9c594a2 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Tue, 12 Feb 2013 08:57:23 +0000 Subject: Use `many=True` for serializers. --- docs/tutorial/1-serialization.md | 29 ++++++++++++++-------- docs/tutorial/2-requests-and-responses.md | 2 +- docs/tutorial/3-class-based-views.md | 2 +- docs/tutorial/4-authentication-and-permissions.md | 2 +- .../5-relationships-and-hyperlinked-apis.md | 6 ++--- 5 files changed, 25 insertions(+), 16 deletions(-) (limited to 'docs') diff --git a/docs/tutorial/1-serialization.md b/docs/tutorial/1-serialization.md index 5f292211..af5e8313 100644 --- a/docs/tutorial/1-serialization.md +++ b/docs/tutorial/1-serialization.md @@ -8,7 +8,7 @@ The tutorial is fairly in-depth, so you should probably get a cookie and a cup o --- -**Note**: The code for this tutorial is available in the [tomchristie/rest-framework-tutorial][repo] repository on GitHub. As pieces of code are introduced, they are committed to this repository. The completed implementation is also online as a sandbox version for testing, [available here][sandbox]. +**Note**: The code for this tutorial is available in the [tomchristie/rest-framework-tutorial][repo] repository on GitHub. The completed implementation is also online as a sandbox version for testing, [available here][sandbox]. --- @@ -150,13 +150,16 @@ Before we go any further we'll familiarize ourselves with using our new Serializ python manage.py shell -Okay, once we've got a few imports out of the way, let's create a code snippet to work with. +Okay, once we've got a few imports out of the way, let's create a couple of code snippets to work with. from snippets.models import Snippet from snippets.serializers import SnippetSerializer from rest_framework.renderers import JSONRenderer from rest_framework.parsers import JSONParser + snippet = Snippet(code='foo = "bar"\n') + snippet.save() + snippet = Snippet(code='print "hello, world"\n') snippet.save() @@ -164,13 +167,13 @@ We've now got a few snippet instances to play with. Let's take a look at serial serializer = SnippetSerializer(snippet) serializer.data - # {'pk': 1, 'title': u'', 'code': u'print "hello, world"\n', 'linenos': False, 'language': u'python', 'style': u'friendly'} + # {'pk': 2, 'title': u'', 'code': u'print "hello, world"\n', 'linenos': False, 'language': u'python', 'style': u'friendly'} At this point we've translated the model instance into python native datatypes. To finalize the serialization process we render the data into `json`. content = JSONRenderer().render(serializer.data) content - # '{"pk": 1, "title": "", "code": "print \\"hello, world\\"\\n", "linenos": false, "language": "python", "style": "friendly"}' + # '{"pk": 2, "title": "", "code": "print \\"hello, world\\"\\n", "linenos": false, "language": "python", "style": "friendly"}' Deserialization is similar. First we parse a stream into python native datatypes... @@ -189,6 +192,12 @@ Deserialization is similar. First we parse a stream into python native datatype Notice how similar the API is to working with forms. The similarity should become even more apparent when we start writing views that use our serializer. +We can also serialize querysets instead of model instances. To do so we simply add a `many=True` flag to the serializer arguments. + + serializer = SnippetSerializer(Snippet.objects.all(), many=True) + serializer.data + # [{'pk': 1, 'title': u'', 'code': u'foo = "bar"\n', 'linenos': False, 'language': u'python', 'style': u'friendly'}, {'pk': 2, 'title': u'', 'code': u'print "hello, world"\n', 'linenos': False, 'language': u'python', 'style': u'friendly'}] + ## Using ModelSerializers Our `SnippetSerializer` class is replicating a lot of information that's also contained in the `Snippet` model. It would be nice if we could keep out code a bit more concise. @@ -237,7 +246,7 @@ The root of our API is going to be a view that supports listing all the existing """ if request.method == 'GET': snippets = Snippet.objects.all() - serializer = SnippetSerializer(snippets) + serializer = SnippetSerializer(snippets, many=True) return JSONResponse(serializer.data) elif request.method == 'POST': @@ -312,19 +321,19 @@ and start up Django's development server In another terminal window, we can test the server. -We can get a list of all of the snippets (we only have one at the moment) +We can get a list of all of the snippets. curl http://127.0.0.1:8000/snippets/ - [{"id": 1, "title": "", "code": "print \"hello, world\"\n", "linenos": false, "language": "python", "style": "friendly"}] + [{"id": 1, "title": "", "code": "foo = \"bar\"\n", "linenos": false, "language": "python", "style": "friendly"}, {"id": 2, "title": "", "code": "print \"hello, world\"\n", "linenos": false, "language": "python", "style": "friendly"}] or we can get a particular snippet by referencing its id - curl http://127.0.0.1:8000/snippets/1/ + curl http://127.0.0.1:8000/snippets/2/ - {"id": 1, "title": "", "code": "print \"hello, world\"\n", "linenos": false, "language": "python", "style": "friendly"} + {"id": 2, "title": "", "code": "print \"hello, world\"\n", "linenos": false, "language": "python", "style": "friendly"} -Similarly, you can have the same json displayed by referencing these URLs from your favorite web browser. +Similarly, you can have the same json displayed by visiting these URLs in a web browser. ## Where are we now diff --git a/docs/tutorial/2-requests-and-responses.md b/docs/tutorial/2-requests-and-responses.md index 340ea28e..566c0dc6 100644 --- a/docs/tutorial/2-requests-and-responses.md +++ b/docs/tutorial/2-requests-and-responses.md @@ -51,7 +51,7 @@ We don't need our `JSONResponse` class anymore, so go ahead and delete that. On """ if request.method == 'GET': snippets = Snippet.objects.all() - serializer = SnippetSerializer(snippets) + serializer = SnippetSerializer(snippets, many=True) return Response(serializer.data) elif request.method == 'POST': diff --git a/docs/tutorial/3-class-based-views.md b/docs/tutorial/3-class-based-views.md index 290ea5e9..e05017c5 100644 --- a/docs/tutorial/3-class-based-views.md +++ b/docs/tutorial/3-class-based-views.md @@ -20,7 +20,7 @@ We'll start by rewriting the root view as a class based view. All this involves """ def get(self, request, format=None): snippets = Snippet.objects.all() - serializer = SnippetSerializer(snippets) + serializer = SnippetSerializer(snippets, many=True) return Response(serializer.data) def post(self, request, format=None): diff --git a/docs/tutorial/4-authentication-and-permissions.md b/docs/tutorial/4-authentication-and-permissions.md index 979421ea..282386c7 100644 --- a/docs/tutorial/4-authentication-and-permissions.md +++ b/docs/tutorial/4-authentication-and-permissions.md @@ -57,7 +57,7 @@ Now that we've got some users to work with, we'd better add representations of t from django.contrib.auth.models import User class UserSerializer(serializers.ModelSerializer): - snippets = serializers.ManyPrimaryKeyRelatedField() + snippets = serializers.PrimaryKeyRelatedField(many=True) class Meta: model = User diff --git a/docs/tutorial/5-relationships-and-hyperlinked-apis.md b/docs/tutorial/5-relationships-and-hyperlinked-apis.md index de856611..81be333b 100644 --- a/docs/tutorial/5-relationships-and-hyperlinked-apis.md +++ b/docs/tutorial/5-relationships-and-hyperlinked-apis.md @@ -70,8 +70,8 @@ The `HyperlinkedModelSerializer` has the following differences from `ModelSerial * It does not include the `pk` field by default. * It includes a `url` field, using `HyperlinkedIdentityField`. -* Relationships use `HyperlinkedRelatedField` and `ManyHyperlinkedRelatedField`, - instead of `PrimaryKeyRelatedField` and `ManyPrimaryKeyRelatedField`. +* Relationships use `HyperlinkedRelatedField`, + instead of `PrimaryKeyRelatedField`. We can easily re-write our existing serializers to use hyperlinking. @@ -86,7 +86,7 @@ We can easily re-write our existing serializers to use hyperlinking. class UserSerializer(serializers.HyperlinkedModelSerializer): - snippets = serializers.ManyHyperlinkedRelatedField(view_name='snippet-detail') + snippets = serializers.HyperlinkedRelatedField(many=True, view_name='snippet-detail') class Meta: model = User -- cgit v1.2.3 From c81b2c64425353a6a872f2d6f94fd9a9ae063b9a Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Tue, 12 Feb 2013 08:57:45 +0000 Subject: Notes on object-level permissions. --- docs/api-guide/permissions.md | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) (limited to 'docs') diff --git a/docs/api-guide/permissions.md b/docs/api-guide/permissions.md index 4845ac88..d47dbc35 100644 --- a/docs/api-guide/permissions.md +++ b/docs/api-guide/permissions.md @@ -106,15 +106,25 @@ The `DjangoModelPermissions` class also supports object-level permissions. Thir # Custom permissions -To implement a custom permission, override `BasePermission` and implement either, or both, of the `.has_permission(self, request, view)` and `.has_object_permission(self, request, view, obj)` methods. +To implement a custom permission, override `BasePermission` and implement either, or both, of the following methods: + +* `.has_permission(self, request, view)` +* `.has_object_permission(self, request, view, obj)` The methods should return `True` if the request should be granted access, and `False` otherwise. +If you need to test if a request is a read operation or a write operation, you should check the request method against the constant `SAFE_METHODS`, which is a tuple containing `'GET'`, `'OPTIONS'` and `'HEAD'`. For example: + + if request.method in permissions.SAFE_METHODS: + # Check permissions for read-only request + else: + # Check permissions for write request + --- **Note**: In versions 2.0 and 2.1, the signature for the permission checks always included an optional `obj` parameter, like so: `.has_permission(self, request, view, obj=None)`. The method would be called twice, first for the global permission checks, with no object supplied, and second for the object-level check when required. -As of version 2.2 this signature has now been replaced with two seperate method calls, which is more explict, and obvious. The old style signature continues to work, but it's use will result in a `PendingDeprecationWarning`, which is silent by default. In 2.3 this will be escalated to a `DeprecationWarning`, and in 2.4 the old-style signature will be removed. +As of version 2.2 this signature has now been replaced with two seperate method calls, which is more explict and obvious. The old style signature continues to work, but it's use will result in a `PendingDeprecationWarning`, which is silent by default. In 2.3 this will be escalated to a `DeprecationWarning`, and in 2.4 the old-style signature will be removed. For more details see the [2.2 release announcement][2.2-announcement]. @@ -129,7 +139,7 @@ The following is an example of a permission class that checks the incoming reque Global permission check for blacklisted IPs. """ - def has_permission(self, request, view, obj=None): + def has_permission(self, request, view): ip_addr = request.META['REMOTE_ADDR'] blacklisted = Blacklist.objects.filter(ip_addr=ip_addr).exists() return not blacklisted @@ -139,6 +149,7 @@ As well as global permissions, that are run against all incoming requests, you c class IsOwnerOrReadOnly(permissions.BasePermission): """ Object-level permission to only allow owners of an object to edit it. + Assumes the model instance has an `owner` attribute. """ def has_object_permission(self, request, view, obj): @@ -152,9 +163,12 @@ As well as global permissions, that are run against all incoming requests, you c Note that the generic views will check the appropriate object level permissions, but if you're writing your own custom views, you'll need to make sure you check the object level permission checks yourself. You can do so by calling `self.check_object_permissions(request, obj)` from the view once you have the object instance. This call will raise an appropriate `APIException` if any object-level permission checks fail, and will otherwise simply return. +Also note that the generic views will only check the object-level permissions for views that retrieve a single model instance. If you require object-level filtering of list views, you'll need to filter the queryset separately. See the [filtering documentation][filtering] for more details. + [cite]: https://developer.apple.com/library/mac/#documentation/security/Conceptual/AuthenticationAndAuthorizationGuide/Authorization/Authorization.html [authentication]: authentication.md [throttling]: throttling.md [contribauth]: https://docs.djangoproject.com/en/1.0/topics/auth/#permissions [guardian]: https://github.com/lukaszb/django-guardian [2.2-announcement]: ../topics/2.2-announcement.md +[filtering]: filtering.md -- cgit v1.2.3 From 36cdefbb4d689e511aa53b46f05ca29106960847 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Tue, 12 Feb 2013 08:58:12 +0000 Subject: Notes on object-level permissions. --- docs/topics/2.2-announcement.md | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) (limited to 'docs') diff --git a/docs/topics/2.2-announcement.md b/docs/topics/2.2-announcement.md index 4ed9f970..262ae61d 100644 --- a/docs/topics/2.2-announcement.md +++ b/docs/topics/2.2-announcement.md @@ -101,6 +101,45 @@ In keeping with Django's CharField API, REST framework's `CharField` will only e The `blank` keyword argument will continue to function, but will raise a `PendingDeprecationWarning`. +### Simpler object-level permissions + +Custom permissions classes previously used the signatute `.has_permission(self, request, view, obj=None)`. This method would be called twice, firstly for the global permissions check, with the `obj` parameter set to `None`, and again for the object-level permissions check when appropriate, with the `obj` parameter set to the relevant model instance. + +The global permissions check and object-level permissions check are now seperated into two seperate methods, which gives a cleaner, more obvious API. + +* Global permission checks now use the `.has_permission(self, request, view)` signature. +* Object-level permission checks use a new method `.has_object_permission(self, request, view, obj)`. + +For example, the following custom permission class: + + class IsOwner(permissions.BasePermission): + """ + Custom permission to only allow owners of an object to view or edit it. + Model instances are expected to include an `owner` attribute. + """ + + def has_permission(self, request, view, obj=None): + if obj is None: + # Ignore global permissions check + return True + + return obj.owner == request.user + +Now becomes: + + class IsOwner(permissions.BasePermission): + """ + Custom permission to only allow owners of an object to view or edit it. + Model instances are expected to include an `owner` attribute. + """ + + def has_object_permission(self, request, view, obj): + return obj.owner == request.user + +If you're overriding the `BasePermission` class, the old-style signature will continue to function, and will correctly handle both global and object-level permissions checks, but it's use will raise a `PendingDeprecationWarning`. + +Note also that the usage of the internal APIs for permission checking on the `View` class has been cleaned up slightly, and is now documented and subject to the deprecation policy in all future versions. + [xordoquy]: https://github.com/xordoquy [django-python-3]: https://docs.djangoproject.com/en/dev/faq/install/#can-i-use-django-with-python-3 [porting-python-3]: https://docs.djangoproject.com/en/dev/topics/python3/ -- cgit v1.2.3 From 112753917d7a9a1effe6e64d9344de3466425733 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Tue, 12 Feb 2013 12:14:29 +0000 Subject: Update release notes --- docs/topics/release-notes.md | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'docs') diff --git a/docs/topics/release-notes.md b/docs/topics/release-notes.md index 4317b83c..63f8539a 100644 --- a/docs/topics/release-notes.md +++ b/docs/topics/release-notes.md @@ -28,8 +28,14 @@ You can determine your currently installed version using `pip freeze`: ### Master +* Python 3 support. * Added a `post_save()` hook to the generic views. * Allow serializers to handle dicts as well as objects. +* Deprecate `ManyRelatedField()` syntax in favor of `RelatedField(many=True)` +* Deprecate `null=True` on relations in favor of `required=False`. +* Deprecate `blank=True` on CharFields, just use `required=False`. +* Deprecate optional `obj` argument in permissions checks in favor of `has_object_permission`. +* Bugfix: Allow serializer output to be cached. * Bugfix: Fix styling on browsable API login. * Bugfix: Fix issue with deserializing empty to-many relations. * Bugfix: Ensure model field validation is still applied for ModelSerializer subclasses with an custom `.restore_object()` method. -- cgit v1.2.3 From f642ee48a666d5cfc3a15cf8c33629bbb6173787 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Tue, 12 Feb 2013 12:14:58 +0000 Subject: Document serializing querysets --- docs/api-guide/serializers.md | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'docs') diff --git a/docs/api-guide/serializers.md b/docs/api-guide/serializers.md index 487502e9..027c343c 100644 --- a/docs/api-guide/serializers.md +++ b/docs/api-guide/serializers.md @@ -80,6 +80,15 @@ By default, serializers must be passed values for all required fields or they wi serializer = CommentSerializer(comment, data={'content': u'foo bar'}, partial=True) # Update `instance` with partial data +## Serializing querysets + +To serialize a queryset instead of an object instance, you should pass the `many=True` flag when instantiating the serializer. + + queryset = Comment.objects.all() + serializer = CommentSerializer(queryset, many=True) + serializer.data + # [{'email': u'leila@example.com', 'content': u'foo bar', 'created': datetime.datetime(2012, 8, 22, 16, 20, 9, 822774)}, {'email': u'jamie@example.com', 'content': u'baz', 'created': datetime.datetime(2013, 1, 12, 16, 12, 45, 104445)}] + ## Validation When deserializing data, you always need to call `is_valid()` before attempting to access the deserialized object. If any validation errors occur, the `.errors` and `.non_field_errors` properties will contain the resulting error messages. -- cgit v1.2.3 From f97aa49809d1a1788c8d524bf274a9b65f740c64 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Tue, 12 Feb 2013 13:55:00 +0000 Subject: Docs on serializer context. --- docs/api-guide/serializers.md | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/api-guide/serializers.md b/docs/api-guide/serializers.md index 027c343c..85189434 100644 --- a/docs/api-guide/serializers.md +++ b/docs/api-guide/serializers.md @@ -123,7 +123,7 @@ To do any other validation that requires access to multiple fields, add a method from rest_framework import serializers class EventSerializer(serializers.Serializer): - description = serializers.CahrField(max_length=100) + description = serializers.CharField(max_length=100) start = serializers.DateTimeField() finish = serializers.DateTimeField() @@ -164,6 +164,17 @@ The `Serializer` class is itself a type of `Field`, and can be used to represent --- +## Including extra context + +There are some cases where you need to provide extra context to the serializer in addition to the object being serialized. One common case is if you're using a serializer that includes hyperlinked relations, which requires the serializer to have access to the current request so that it can properly generate fully qualified URLs. + +You can provide arbitrary additional context by passing a `context` argument when instantiating the serializer. For example: + + serializer = AccountSerializer(account, context={'request': request}) + serializer.data + # {'id': 6, 'owner': u'denvercoder9', 'created': datetime.datetime(2013, 2, 12, 09, 44, 56, 678870), 'details': 'http://example.com/accounts/6/details'} + +The context dictionary can be used within any serializer field logic, such as a custom `.to_native()` method, by accessing the `self.context` attribute. ## Creating custom fields -- cgit v1.2.3 From edaf031935ae04db48d078452d46c71b6b5d7ebe Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Tue, 12 Feb 2013 20:14:47 +0000 Subject: Notes on explicit hyperlink relations behavior --- docs/topics/2.2-announcement.md | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'docs') diff --git a/docs/topics/2.2-announcement.md b/docs/topics/2.2-announcement.md index 262ae61d..65c05267 100644 --- a/docs/topics/2.2-announcement.md +++ b/docs/topics/2.2-announcement.md @@ -140,6 +140,12 @@ If you're overriding the `BasePermission` class, the old-style signature will co Note also that the usage of the internal APIs for permission checking on the `View` class has been cleaned up slightly, and is now documented and subject to the deprecation policy in all future versions. +## More explicit hyperlink relations behavior + +When using a serializer with a `HyperlinkedRelatedField` or `HyperlinkedIdentityField`, the hyperlinks would previously use absolute URLs if the serializer context included a `'request'` key, and fallback to using relative URLs otherwise. This could lead to non-obvious behavior, as it might not be clear why some serializers generated absolute URLs, and others do not. + +From version 2.2 onwards, serializers with hyperlinked relationships *always* require a `'request'` key to be supplied in the context dictionary. The implicit behavior will continue to function, but it's use will raise a `PendingDeprecationWarning`. + [xordoquy]: https://github.com/xordoquy [django-python-3]: https://docs.djangoproject.com/en/dev/faq/install/#can-i-use-django-with-python-3 [porting-python-3]: https://docs.djangoproject.com/en/dev/topics/python3/ -- cgit v1.2.3 From a08fa7c71ed026cad0ec9832b34f95fe38725e53 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Tue, 12 Feb 2013 22:05:17 +0000 Subject: Add deprecation policy to release notes. --- docs/topics/release-notes.md | 34 ++++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) (limited to 'docs') diff --git a/docs/topics/release-notes.md b/docs/topics/release-notes.md index 63f8539a..8756430f 100644 --- a/docs/topics/release-notes.md +++ b/docs/topics/release-notes.md @@ -8,9 +8,23 @@ Minor version numbers (0.0.x) are used for changes that are API compatible. You should be able to upgrade between minor point releases without any other code changes. -Medium version numbers (0.x.0) may include minor API changes. You should read the release notes carefully before upgrading between medium point releases. +Medium version numbers (0.x.0) may include API changes, in line with the [deprecation policy][deprecation-policy]. You should read the release notes carefully before upgrading between medium point releases. -Major version numbers (x.0.0) are reserved for project milestones. No major point releases are currently planned. +Major version numbers (x.0.0) are reserved for substantial project milestones. No major point releases are currently planned. + +## Deprecation policy + +REST framework releases follow a formal deprecation policy, which is in line with [Django's deprecation policy][django-deprecation-policy]. + +The timeline for deprecation of a feature present in version 1.0 would work as follows: + +* Version 1.1 would remain **fully backwards compatible** with 1.0, but would raise `PendingDeprecationWarning` warnings if you use the feature that are due to be deprecated. These warnings are **silent by default**, but can be explicitly enabled when you're ready to start migrating any required changes. For example if you start running your tests using `python -Wd manage.py test`, you'll be warned of any API changes you need to make. + +* Version 1.2 would escalate these warnings to `DeprecationWarning`, which is loud by default. + +* Version 1.3 would remove the deprecated bits of API entirely. + +Note that in line with Django's policy, any parts of the framework not mentioned in the documentation should generally be considered private API, and may be subject to change. ## Upgrading @@ -24,9 +38,11 @@ You can determine your currently installed version using `pip freeze`: --- -## 2.1.x series +## 2.2.x series + +### 2.2.0 -### Master +**Date**: 13th Feb 2013 * Python 3 support. * Added a `post_save()` hook to the generic views. @@ -35,11 +51,18 @@ You can determine your currently installed version using `pip freeze`: * Deprecate `null=True` on relations in favor of `required=False`. * Deprecate `blank=True` on CharFields, just use `required=False`. * Deprecate optional `obj` argument in permissions checks in favor of `has_object_permission`. +* Deprecate implicit hyperlinked relations behavior. * Bugfix: Allow serializer output to be cached. * Bugfix: Fix styling on browsable API login. * Bugfix: Fix issue with deserializing empty to-many relations. * Bugfix: Ensure model field validation is still applied for ModelSerializer subclasses with an custom `.restore_object()` method. +**Note**: See the [2.2 announcement][2.2-announcement] for full details. + +--- + +## 2.1.x series + ### 2.1.17 **Date**: 26th Jan 2013 @@ -356,6 +379,9 @@ This change will not affect user code, so long as it's following the recommended * Initial release. [cite]: http://www.catb.org/~esr/writings/cathedral-bazaar/cathedral-bazaar/ar01s04.html +[deprecation-policy]: #deprecation-policy +[django-deprecation-policy]: https://docs.djangoproject.com/en/dev/internals/release-process/#internal-release-deprecation-policy +[2.2-announcement]: 2.2-announcement.md [staticfiles14]: https://docs.djangoproject.com/en/1.4/howto/static-files/#with-a-template-tag [staticfiles13]: https://docs.djangoproject.com/en/1.3/howto/static-files/#with-a-template-tag [2.1.0-notes]: https://groups.google.com/d/topic/django-rest-framework/Vv2M0CMY9bg/discussion -- cgit v1.2.3 From 891b197f0b5eb19fc86f3c1ced5c9b49749afeb6 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Tue, 12 Feb 2013 22:06:13 +0000 Subject: Drop issue management section --- docs/topics/2.2-announcement.md | 4 ---- 1 file changed, 4 deletions(-) (limited to 'docs') diff --git a/docs/topics/2.2-announcement.md b/docs/topics/2.2-announcement.md index 65c05267..9523eebf 100644 --- a/docs/topics/2.2-announcement.md +++ b/docs/topics/2.2-announcement.md @@ -30,10 +30,6 @@ As of the 2.2 merge, we've also hit an impressive milestone. The number of comm Our [mailing list][mailing-list] and #restframework IRC channel are also very active, and we've got a really impressive rate of development both on REST framework itself, and on third party packages such as the great [django-rest-framework-docs][django-rest-framework-docs] package from [Marc Gibbons][marcgibbons]. -## Issue management - -All the design work that went into version 2 of Django REST framework has made keeping on top of issues much easier. We've been super-focused on keeping the [issues list][issues] strictly under control, and we've hit another important milestone. At the point of releasing 2.2 there are currently **no open 'bug' tickets**, and the plan is to keep it that way for as much of the time as possible. - ## API changes The 2.2 release makes a few changes to the serializer fields API, in order to make it more consistent, simple, and easier to use. -- cgit v1.2.3 From 3f529dc25d66fba0c6f94944ebc92f338c86434d Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Tue, 12 Feb 2013 22:06:20 +0000 Subject: Typo --- docs/topics/2.2-announcement.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/topics/2.2-announcement.md b/docs/topics/2.2-announcement.md index 9523eebf..8a7ae326 100644 --- a/docs/topics/2.2-announcement.md +++ b/docs/topics/2.2-announcement.md @@ -16,7 +16,7 @@ We've now introduced an official deprecation policy, which is in line with [Djan The timeline for deprecation works as follows: -* Version 2.2 introduces some API changes as detailed in the release notes. It remains fully backwards compatible with 2.1, but will raise `PendingDeprecationWarning` warnings if you use bits API that are due to be deprecated. These warnings are silent by default, but can be explicitly enabled when you're ready to start migrating any required changes. For example if you start running your tests using `python -Wd manage.py test`, you'll be warned of any API changes you need to make. +* Version 2.2 introduces some API changes as detailed in the release notes. It remains fully backwards compatible with 2.1, but will raise `PendingDeprecationWarning` warnings if you use bits of API that are due to be deprecated. These warnings are silent by default, but can be explicitly enabled when you're ready to start migrating any required changes. For example if you start running your tests using `python -Wd manage.py test`, you'll be warned of any API changes you need to make. * Version 2.3 will escalate these warnings to `DeprecationWarning`, which is loud by default. -- cgit v1.2.3 From b7a5c4b050ab5bd0125e6f7af4e0546c98125282 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Tue, 12 Feb 2013 23:13:48 +0000 Subject: Notes on creating a custom `obtain_auth_token` view. Fixes #641. --- docs/api-guide/authentication.md | 2 ++ 1 file changed, 2 insertions(+) (limited to 'docs') diff --git a/docs/api-guide/authentication.md b/docs/api-guide/authentication.md index 9c899f17..8c1d1185 100644 --- a/docs/api-guide/authentication.md +++ b/docs/api-guide/authentication.md @@ -167,6 +167,8 @@ The `obtain_auth_token` view will return a JSON response when valid `username` a { 'token' : '9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b' } +Note that the default `obtain_auth_token` view explicitly uses JSON requests and responses, rather than using default renderer and parser classes in your settings. If you need a customized version of the `obtain_auth_token` view, you can do so by overriding the `ObtainAuthToken` view class, and using that in your url conf instead. + ## SessionAuthentication This authentication scheme uses Django's default session backend for authentication. Session authentication is appropriate for AJAX clients that are running in the same session context as your website. -- cgit v1.2.3 From 195adf6ed44e34acce08e306c6ced0340c28798d Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Tue, 12 Feb 2013 23:17:19 +0000 Subject: Update release notes. --- docs/topics/release-notes.md | 1 + 1 file changed, 1 insertion(+) (limited to 'docs') diff --git a/docs/topics/release-notes.md b/docs/topics/release-notes.md index 8756430f..06e45674 100644 --- a/docs/topics/release-notes.md +++ b/docs/topics/release-notes.md @@ -52,6 +52,7 @@ You can determine your currently installed version using `pip freeze`: * Deprecate `blank=True` on CharFields, just use `required=False`. * Deprecate optional `obj` argument in permissions checks in favor of `has_object_permission`. * Deprecate implicit hyperlinked relations behavior. +* Bugfix: Fix broken DjangoModelPermissions. * Bugfix: Allow serializer output to be cached. * Bugfix: Fix styling on browsable API login. * Bugfix: Fix issue with deserializing empty to-many relations. -- cgit v1.2.3 From 0b2adaa9425fae0e82dd94b1ec15a56b904eac53 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Tue, 12 Feb 2013 23:17:41 +0000 Subject: Drop note on object-level permissions. Not yet supported by DjangoModelPermissions. --- docs/api-guide/permissions.md | 2 -- 1 file changed, 2 deletions(-) (limited to 'docs') diff --git a/docs/api-guide/permissions.md b/docs/api-guide/permissions.md index d47dbc35..2db6ce1e 100644 --- a/docs/api-guide/permissions.md +++ b/docs/api-guide/permissions.md @@ -100,8 +100,6 @@ The default behaviour can also be overridden to support custom model permissions To use custom model permissions, override `DjangoModelPermissions` and set the `.perms_map` property. Refer to the source code for details. -The `DjangoModelPermissions` class also supports object-level permissions. Third-party authorization backends such as [django-guardian][guardian] that provide object-level permissions should work just fine with `DjangoModelPermissions` without any custom configuration required. - --- # Custom permissions -- cgit v1.2.3 From 77db00f449d88ca701b82e9f1d9924b3cc026638 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Wed, 13 Feb 2013 09:05:16 +0000 Subject: Tweak title --- docs/topics/2.2-announcement.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/topics/2.2-announcement.md b/docs/topics/2.2-announcement.md index 8a7ae326..e24fc615 100644 --- a/docs/topics/2.2-announcement.md +++ b/docs/topics/2.2-announcement.md @@ -1,4 +1,4 @@ -# REST framework 2.2 release notes +# REST framework 2.2 announcement The 2.2 release represents an important point for REST framework, with the addition of Python 3 support, and the introduction of an official deprecation policy. -- cgit v1.2.3 From f8eb222ec11df54a8fbae5cf6cb74fb0d4bddffe Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Wed, 13 Feb 2013 14:08:56 +0000 Subject: Add links to 2.2 announcement --- docs/index.md | 2 ++ docs/template.html | 1 + 2 files changed, 3 insertions(+) (limited to 'docs') diff --git a/docs/index.md b/docs/index.md index 37e7cb3c..0059e17b 100644 --- a/docs/index.md +++ b/docs/index.md @@ -116,6 +116,7 @@ General guides to using REST framework. * [The Browsable API][browsableapi] * [REST, Hypermedia & HATEOAS][rest-hypermedia-hateoas] * [2.0 Announcement][rest-framework-2-announcement] +* [2.2 Announcement][2.2-announcement] * [Release Notes][release-notes] * [Credits][credits] @@ -211,6 +212,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. [rest-hypermedia-hateoas]: topics/rest-hypermedia-hateoas.md [contributing]: topics/contributing.md [rest-framework-2-announcement]: topics/rest-framework-2-announcement.md +[2.2-announcement]: topics/2.2-announcement.md [release-notes]: topics/release-notes.md [credits]: topics/credits.md diff --git a/docs/template.html b/docs/template.html index 2a87e92b..e0f88daf 100644 --- a/docs/template.html +++ b/docs/template.html @@ -94,6 +94,7 @@
  • The Browsable API
  • REST, Hypermedia & HATEOAS
  • 2.0 Announcement
  • +
  • 2.2 Announcement
  • Release Notes
  • Credits
  • -- cgit v1.2.3 From 569dc67a1220f0b577e7873bf7ee3ac54cf60143 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Wed, 13 Feb 2013 14:40:02 +0000 Subject: Username tweak. --- docs/topics/credits.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'docs') diff --git a/docs/topics/credits.md b/docs/topics/credits.md index b84f1357..e4abd286 100644 --- a/docs/topics/credits.md +++ b/docs/topics/credits.md @@ -19,7 +19,7 @@ The following people have helped make REST framework great. * Craig Blaszczyk - [jakul] * Garcia Solero - [garciasolero] * Tom Drummond - [devioustree] -* Danilo Bargen - [gwrtheyrn] +* Danilo Bargen - [dbrgn] * Andrew McCloud - [amccloud] * Thomas Steinacher - [thomasst] * Meurig Freeman - [meurig] @@ -155,7 +155,7 @@ You can also contact [@_tomchristie][twitter] directly on twitter. [jakul]: https://github.com/jakul [garciasolero]: https://github.com/garciasolero [devioustree]: https://github.com/devioustree -[gwrtheyrn]: https://github.com/gwrtheyrn +[dbrgn]: https://github.com/dbrgn [amccloud]: https://github.com/amccloud [thomasst]: https://github.com/thomasst [meurig]: https://github.com/meurig -- cgit v1.2.3 From 876bd67888c851826288d4c2a669c7def9956858 Mon Sep 17 00:00:00 2001 From: floppya Date: Wed, 13 Feb 2013 13:59:00 -0600 Subject: Minor doc fixes Fixes misspelling of "primitive" and removes an awkward "with". --- docs/api-guide/pagination.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/api-guide/pagination.md b/docs/api-guide/pagination.md index 51c0fb4b..13d4760a 100644 --- a/docs/api-guide/pagination.md +++ b/docs/api-guide/pagination.md @@ -37,7 +37,7 @@ We could now return that data in a `Response` object, and it would be rendered i ## Paginating QuerySets -Our first example worked because we were using primative objects. If we wanted to paginate a queryset or other complex data, we'd need to specify a serializer to use to serialize the result set itself with. +Our first example worked because we were using primitive objects. If we wanted to paginate a queryset or other complex data, we'd need to specify a serializer to use to serialize the result set itself. We can do this using the `object_serializer_class` attribute on the inner `Meta` class of the pagination serializer. For example. -- cgit v1.2.3 From 2eab7b9f59a9e4e7deedd823bdaf135e0a9b01a1 Mon Sep 17 00:00:00 2001 From: Stephan Groß Date: Thu, 14 Feb 2013 09:04:09 +0100 Subject: thanks @floppya for docs fix --- 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 e4abd286..1320d4d4 100644 --- a/docs/topics/credits.md +++ b/docs/topics/credits.md @@ -102,6 +102,7 @@ The following people have helped make REST framework great. * Andrea de Marco - [z4r] * Fernando Rocha - [fernandogrd] * Xavier Ordoquy - [xordoquy] +* Adam Wentz - [floppya] Many thanks to everyone who's contributed to the project. @@ -238,3 +239,4 @@ You can also contact [@_tomchristie][twitter] directly on twitter. [z4r]: https://github.com/z4r [fernandogrd]: https://github.com/fernandogrd [xordoquy]: https://github.com/xordoquy +[floppya]: https://github.com/floppya -- cgit v1.2.3 From 34145408cb73213c2f6c1e9ab53795e6d7e3a3f6 Mon Sep 17 00:00:00 2001 From: eofs Date: Thu, 14 Feb 2013 13:21:54 +0200 Subject: Missing imports added --- docs/tutorial/1-serialization.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'docs') diff --git a/docs/tutorial/1-serialization.md b/docs/tutorial/1-serialization.md index af5e8313..53d24136 100644 --- a/docs/tutorial/1-serialization.md +++ b/docs/tutorial/1-serialization.md @@ -109,7 +109,7 @@ The first thing we need to get started on our Web API is provide a way of serial from django.forms import widgets from rest_framework import serializers - from snippets.models import Snippet + from snippets.models import Snippet, LANGUAGE_CHOICES, STYLE_CHOICES class SnippetSerializer(serializers.Serializer): @@ -119,9 +119,9 @@ The first thing we need to get started on our Web API is provide a way of serial code = serializers.CharField(widget=widgets.Textarea, max_length=100000) linenos = serializers.BooleanField(required=False) - language = serializers.ChoiceField(choices=models.LANGUAGE_CHOICES, + language = serializers.ChoiceField(choices=LANGUAGE_CHOICES, default='python') - style = serializers.ChoiceField(choices=models.STYLE_CHOICES, + style = serializers.ChoiceField(choices=STYLE_CHOICES, default='friendly') def restore_object(self, attrs, instance=None): -- cgit v1.2.3 From 0d3e23f0d379f4df7ac7cd8f42cae2d303558852 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Thu, 14 Feb 2013 13:02:38 +0000 Subject: Update release notes. --- docs/topics/release-notes.md | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'docs') diff --git a/docs/topics/release-notes.md b/docs/topics/release-notes.md index 06e45674..406923f4 100644 --- a/docs/topics/release-notes.md +++ b/docs/topics/release-notes.md @@ -40,6 +40,11 @@ You can determine your currently installed version using `pip freeze`: ## 2.2.x series +### Master + +* Bugfix: request.DATA should return an empty `QueryDict` with no data, not `None`. +* Bugfix: Remove unneeded field validation, which caused extra querys. + ### 2.2.0 **Date**: 13th Feb 2013 -- cgit v1.2.3 From de029561d0cbb090c0d704811551b2d611472288 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Thu, 14 Feb 2013 13:09:42 +0000 Subject: Docs tweaks. --- docs/index.md | 2 +- docs/topics/release-notes.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'docs') diff --git a/docs/index.md b/docs/index.md index 0059e17b..32b42419 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,7 +1,7 @@

    - + Travis build image diff --git a/docs/topics/release-notes.md b/docs/topics/release-notes.md index 406923f4..3f3f8786 100644 --- a/docs/topics/release-notes.md +++ b/docs/topics/release-notes.md @@ -43,7 +43,7 @@ You can determine your currently installed version using `pip freeze`: ### Master * Bugfix: request.DATA should return an empty `QueryDict` with no data, not `None`. -* Bugfix: Remove unneeded field validation, which caused extra querys. +* Bugfix: Remove unneeded field validation, which caused extra queries. ### 2.2.0 -- cgit v1.2.3 From 5a5df18d182d43d993da8f0b5d4a8888e868fcae Mon Sep 17 00:00:00 2001 From: Andreas Pelme Date: Thu, 14 Feb 2013 21:19:51 +0100 Subject: Added a serializer TimeField --- docs/api-guide/fields.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/api-guide/fields.md b/docs/api-guide/fields.md index 3f8a36e2..8c28273b 100644 --- a/docs/api-guide/fields.md +++ b/docs/api-guide/fields.md @@ -199,10 +199,16 @@ If you want to override this behavior, you'll need to declare the `DateTimeField class CommentSerializer(serializers.ModelSerializer): created = serializers.DateTimeField() - + class Meta: model = Comment +## TimeField + +A time representation. + +Corresponds to `django.db.models.fields.TimeField` + ## IntegerField An integer representation. -- cgit v1.2.3 From 725741198b9e185499662836b569cd729e1e9eb6 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Fri, 15 Feb 2013 09:05:55 +0000 Subject: Python 2.6.5+ required --- docs/index.md | 2 +- docs/topics/2.2-announcement.md | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'docs') diff --git a/docs/index.md b/docs/index.md index 32b42419..0188accf 100644 --- a/docs/index.md +++ b/docs/index.md @@ -27,7 +27,7 @@ There is also a sandbox API you can use for testing purposes, [available here][s REST framework requires the following: -* Python (2.6, 2.7, 3.2, 3.3) +* Python (2.6.5+, 2.7, 3.2, 3.3) * Django (1.3, 1.4, 1.5) The following packages are optional: diff --git a/docs/topics/2.2-announcement.md b/docs/topics/2.2-announcement.md index e24fc615..0ef9fce8 100644 --- a/docs/topics/2.2-announcement.md +++ b/docs/topics/2.2-announcement.md @@ -30,9 +30,11 @@ As of the 2.2 merge, we've also hit an impressive milestone. The number of comm Our [mailing list][mailing-list] and #restframework IRC channel are also very active, and we've got a really impressive rate of development both on REST framework itself, and on third party packages such as the great [django-rest-framework-docs][django-rest-framework-docs] package from [Marc Gibbons][marcgibbons]. +--- + ## API changes -The 2.2 release makes a few changes to the serializer fields API, in order to make it more consistent, simple, and easier to use. +The 2.2 release makes a few changes to the API, in order to make it more consistent, simple, and easier to use. ### Cleaner to-many related fields @@ -136,7 +138,7 @@ If you're overriding the `BasePermission` class, the old-style signature will co Note also that the usage of the internal APIs for permission checking on the `View` class has been cleaned up slightly, and is now documented and subject to the deprecation policy in all future versions. -## More explicit hyperlink relations behavior +### More explicit hyperlink relations behavior When using a serializer with a `HyperlinkedRelatedField` or `HyperlinkedIdentityField`, the hyperlinks would previously use absolute URLs if the serializer context included a `'request'` key, and fallback to using relative URLs otherwise. This could lead to non-obvious behavior, as it might not be clear why some serializers generated absolute URLs, and others do not. -- cgit v1.2.3 From e919cb1b57a27f581c07080e341a86421df78a88 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Fri, 15 Feb 2013 09:09:34 +0000 Subject: Note python compatibility. --- docs/topics/2.2-announcement.md | 3 +++ 1 file changed, 3 insertions(+) (limited to 'docs') diff --git a/docs/topics/2.2-announcement.md b/docs/topics/2.2-announcement.md index 0ef9fce8..d7164ce4 100644 --- a/docs/topics/2.2-announcement.md +++ b/docs/topics/2.2-announcement.md @@ -10,6 +10,8 @@ Django 1.6's Python 3 support is expected to be officially labeled as 'productio If you want to start ensuring that your own projects are Python 3 ready, we can highly recommend Django's [Porting to Python 3][porting-python-3] documentation. +Django REST framework's Python 2.6 support now requires 2.6.5 or above, in line with [Django 1.5's Python compatibility][python-compat]. + ## Deprecation policy We've now introduced an official deprecation policy, which is in line with [Django's deprecation policy][django-deprecation-policy]. This policy will make it easy for you to continue to track the latest, greatest version of REST framework. @@ -147,6 +149,7 @@ From version 2.2 onwards, serializers with hyperlinked relationships *always* re [xordoquy]: https://github.com/xordoquy [django-python-3]: https://docs.djangoproject.com/en/dev/faq/install/#can-i-use-django-with-python-3 [porting-python-3]: https://docs.djangoproject.com/en/dev/topics/python3/ +[python-compat]: https://docs.djangoproject.com/en/dev/releases/1.5/#python-compatibility [django-deprecation-policy]: https://docs.djangoproject.com/en/dev/internals/release-process/#internal-release-deprecation-policy [credits]: http://django-rest-framework.org/topics/credits.html [mailing-list]: https://groups.google.com/forum/?fromgroups#!forum/django-rest-framework -- cgit v1.2.3 From d05b950945ffe012de63f750ba5b98b14cfc4b9a Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Fri, 15 Feb 2013 09:16:49 +0000 Subject: Update release notes. --- docs/topics/release-notes.md | 2 ++ 1 file changed, 2 insertions(+) (limited to 'docs') diff --git a/docs/topics/release-notes.md b/docs/topics/release-notes.md index 3f3f8786..d5444f72 100644 --- a/docs/topics/release-notes.md +++ b/docs/topics/release-notes.md @@ -42,6 +42,8 @@ You can determine your currently installed version using `pip freeze`: ### Master +* Added TimeField. +* Serializer fields can be mapped to any method that takes no args, or only takes kwargs which have defaults. * Bugfix: request.DATA should return an empty `QueryDict` with no data, not `None`. * Bugfix: Remove unneeded field validation, which caused extra queries. -- cgit v1.2.3 From 50a9070e469dfc3c1018e9eee8ac9fe8c1a5f552 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Fri, 15 Feb 2013 09:19:10 +0000 Subject: Added @pelme, for TimeField addition. Refs #660. --- 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 1320d4d4..bb41ef5f 100644 --- a/docs/topics/credits.md +++ b/docs/topics/credits.md @@ -103,6 +103,7 @@ The following people have helped make REST framework great. * Fernando Rocha - [fernandogrd] * Xavier Ordoquy - [xordoquy] * Adam Wentz - [floppya] +* Andreas Pelme - [pelme] Many thanks to everyone who's contributed to the project. @@ -240,3 +241,4 @@ You can also contact [@_tomchristie][twitter] directly on twitter. [fernandogrd]: https://github.com/fernandogrd [xordoquy]: https://github.com/xordoquy [floppya]: https://github.com/floppya +[pelme]: https://github.com/pelme -- cgit v1.2.3 From 618606888ab34418998d1abfe4668804038ff22f Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Fri, 15 Feb 2013 09:27:37 +0000 Subject: Mention caching. Closes #659. --- docs/api-guide/throttling.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'docs') diff --git a/docs/api-guide/throttling.md b/docs/api-guide/throttling.md index 923593bc..1abd49f4 100644 --- a/docs/api-guide/throttling.md +++ b/docs/api-guide/throttling.md @@ -6,8 +6,6 @@ > > [Twitter API rate limiting response][cite] -[cite]: https://dev.twitter.com/docs/error-codes-responses - Throttling is similar to [permissions], in that it determines if a request should be authorized. Throttles indicate a temporary state, and are used to control the rate of requests that clients can make to an API. As with permissions, multiple throttles may be used. Your API might have a restrictive throttle for unauthenticated requests, and a less restrictive throttle for authenticated requests. @@ -63,6 +61,10 @@ Or, if you're using the `@api_view` decorator with function based views. } return Response(content) +## Setting up the cache + +The throttle classes provided by REST framework use Django's cache backend. You should make sure that you've set appropriate [cache settings][cache-setting]. The default value of `LocMemCache` backend should be okay for simple setups. See Django's [cache documentation][cache-docs] for more details. + --- # API Reference @@ -162,4 +164,7 @@ The following is an example of a rate throttle, that will randomly throttle 1 in def allow_request(self, request, view): return random.randint(1, 10) == 1 +[cite]: https://dev.twitter.com/docs/error-codes-responses [permissions]: permissions.md +[cache-setting]: https://docs.djangoproject.com/en/dev/ref/settings/#caches +[cache-docs]: https://docs.djangoproject.com/en/dev/topics/cache/#setting-up-the-cache \ No newline at end of file -- cgit v1.2.3 From 66a6ffaf957405691d0714fc422b46a6927639a7 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Tue, 19 Feb 2013 17:09:28 +0000 Subject: Fix typos. --- docs/api-guide/relations.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'docs') diff --git a/docs/api-guide/relations.md b/docs/api-guide/relations.md index 25fca475..5a9d74b0 100644 --- a/docs/api-guide/relations.md +++ b/docs/api-guide/relations.md @@ -43,7 +43,7 @@ In order to explain the various types of relational fields, we'll use a couple o For example, the following serializer. - class AlbumSerializer(serializer.ModelSerializer): + class AlbumSerializer(serializers.ModelSerializer): tracks = RelatedField(many=True) class Meta: @@ -75,7 +75,7 @@ This field is read only. For example, the following serializer: - class AlbumSerializer(serializer.ModelSerializer): + class AlbumSerializer(serializers.ModelSerializer): tracks = PrimaryKeyRelatedField(many=True, read_only=True) class Meta: @@ -109,7 +109,7 @@ By default this field is read-write, although you can change this behavior using For example, the following serializer: - class AlbumSerializer(serializer.ModelSerializer): + class AlbumSerializer(serializers.ModelSerializer): tracks = HyperlinkedRelatedField(many=True, read_only=True, view_name='track-detail') @@ -149,7 +149,7 @@ By default this field is read-write, although you can change this behavior using For example, the following serializer: - class AlbumSerializer(serializer.ModelSerializer): + class AlbumSerializer(serializers.ModelSerializer): tracks = SlugRelatedField(many=True, read_only=True, slug_field='title') class Meta: @@ -223,12 +223,12 @@ Note that nested relationships are currently read-only. For read-write relation For example, the following serializer: - class TrackSerializer(serializer.ModelSerializer): + class TrackSerializer(serializers.ModelSerializer): class Meta: model = Track fields = ('order', 'title') - class AlbumSerializer(serializer.ModelSerializer): + class AlbumSerializer(serializers.ModelSerializer): tracks = TrackSerializer(many=True) class Meta: @@ -265,7 +265,7 @@ For, example, we could define a relational field, to serialize a track to a cust duration = time.strftime('%M:%S', time.gmtime(value.duration)) return 'Track %d: %s (%s)' % (value.order, value.name, duration) - class AlbumSerializer(serializer.ModelSerializer): + class AlbumSerializer(serializers.ModelSerializer): tracks = TrackListingField(many=True) class Meta: @@ -295,13 +295,13 @@ Note that reverse relationships are not automatically generated by the `ModelSer **The following will not work:** - class AlbumSerializer(serializer.ModelSerializer): + class AlbumSerializer(serializers.ModelSerializer): class Meta: fields = ('tracks', ...) Instead, you must explicitly add it to the serializer. For example: - class AlbumSerializer(serializer.ModelSerializer): + class AlbumSerializer(serializers.ModelSerializer): tracks = serializers.PrimaryKeyRelationship(many=True) ... @@ -315,7 +315,7 @@ The best way to ensure this is typically to make sure that the relationship on t Alternatively, you can use the `source` argument on the serializer field, to use a different accessor attribute than the field name. For example. - class AlbumSerializer(serializer.ModelSerializer): + class AlbumSerializer(serializers.ModelSerializer): tracks = serializers.PrimaryKeyRelationship(many=True, source='track_set') See the Django documentation on [reverse relationships][reverse-relationships] for more details. -- cgit v1.2.3 From c5cf51cf511c84ab3e446376ff38170dcd421958 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Tue, 19 Feb 2013 17:16:48 +0000 Subject: Fix typos. --- docs/api-guide/relations.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'docs') diff --git a/docs/api-guide/relations.md b/docs/api-guide/relations.md index 5a9d74b0..623fe1a9 100644 --- a/docs/api-guide/relations.md +++ b/docs/api-guide/relations.md @@ -302,7 +302,7 @@ Note that reverse relationships are not automatically generated by the `ModelSer Instead, you must explicitly add it to the serializer. For example: class AlbumSerializer(serializers.ModelSerializer): - tracks = serializers.PrimaryKeyRelationship(many=True) + tracks = serializers.PrimaryKeyRelatedField(many=True) ... By default, the field will uses the same accessor as it's field name to retrieve the relationship, so in this example, `Album` instances would need to have the `tracks` attribute for this relationship to work. @@ -316,7 +316,7 @@ The best way to ensure this is typically to make sure that the relationship on t Alternatively, you can use the `source` argument on the serializer field, to use a different accessor attribute than the field name. For example. class AlbumSerializer(serializers.ModelSerializer): - tracks = serializers.PrimaryKeyRelationship(many=True, source='track_set') + tracks = serializers.PrimaryKeyRelatedField(many=True, source='track_set') See the Django documentation on [reverse relationships][reverse-relationships] for more details. -- cgit v1.2.3 From fc5f982ccc761efd5a6ee320dad7b97ebf9cfad8 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Wed, 20 Feb 2013 11:12:54 +0200 Subject: Don’t use my old nickname in credits. --- docs/topics/credits.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/topics/credits.md b/docs/topics/credits.md index bb41ef5f..990f3cb6 100644 --- a/docs/topics/credits.md +++ b/docs/topics/credits.md @@ -4,7 +4,7 @@ The following people have helped make REST framework great. * Tom Christie - [tomchristie] * Marko Tibold - [markotibold] -* Paul Bagwell - [pbgwl] +* Paul Miller - [paulmillr] * Sébastien Piquemal - [sebpiq] * Carmen Wick - [cwick] * Alex Ehlke - [aehlke] -- cgit v1.2.3 From 47a4f0863d08e4b839ea3bbd7308ecc0f995b7d9 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Wed, 20 Feb 2013 09:18:54 +0000 Subject: Update link to @paulmillr. Refs #668. --- docs/topics/credits.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/topics/credits.md b/docs/topics/credits.md index 990f3cb6..e546548e 100644 --- a/docs/topics/credits.md +++ b/docs/topics/credits.md @@ -142,7 +142,7 @@ You can also contact [@_tomchristie][twitter] directly on twitter. [tomchristie]: https://github.com/tomchristie [markotibold]: https://github.com/markotibold -[pbgwl]: https://github.com/pbgwl +[paulmillr]: https://github.com/paulmillr [sebpiq]: https://github.com/sebpiq [cwick]: https://github.com/cwick [aehlke]: https://github.com/aehlke -- cgit v1.2.3 From 31f3fa63b2758d1e16f6814f4ac18647412bdddb Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Fri, 22 Feb 2013 08:39:50 +0000 Subject: Tweak TemplateHTMLRenderer docs. --- docs/api-guide/renderers.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/api-guide/renderers.md b/docs/api-guide/renderers.md index 4c1fdc53..ca9a6694 100644 --- a/docs/api-guide/renderers.md +++ b/docs/api-guide/renderers.md @@ -115,7 +115,7 @@ The TemplateHTMLRenderer will create a `RequestContext`, using the `response.dat The template name is determined by (in order of preference): -1. An explicit `.template_name` attribute set on the response. +1. An explicit `template_name` argument passed to the response. 2. An explicit `.template_name` attribute set on this class. 3. The return result of calling `view.get_template_names()`. -- cgit v1.2.3 From dcee027fa97f015ff3b87f0fd72b7995cdd6e155 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Fri, 22 Feb 2013 13:17:22 +0000 Subject: defusedxml for security fix. As per: http://blog.python.org/2013/02/announcing-defusedxml-fixes-for-xml.html --- docs/index.md | 2 ++ 1 file changed, 2 insertions(+) (limited to 'docs') diff --git a/docs/index.md b/docs/index.md index 0188accf..b2c04735 100644 --- a/docs/index.md +++ b/docs/index.md @@ -34,6 +34,7 @@ The following packages are optional: * [Markdown][markdown] (2.1.0+) - Markdown support for the browseable API. * [PyYAML][yaml] (3.10+) - YAML content-type support. +* [defusedxml][defusedxml] (0.3+) - XML content-type support. * [django-filter][django-filter] (0.5.4+) - Filtering support. ## Installation @@ -173,6 +174,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. [urlobject]: https://github.com/zacharyvoase/urlobject [markdown]: http://pypi.python.org/pypi/Markdown/ [yaml]: http://pypi.python.org/pypi/PyYAML +[defusedxml]: https://pypi.python.org/pypi/defusedxml [django-filter]: http://pypi.python.org/pypi/django-filter [0.4]: https://github.com/tomchristie/django-rest-framework/tree/0.4.X [image]: img/quickstart.png -- cgit v1.2.3 From b3019d9824c0ba2f907e16202f6e9400ab7ae80e Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Fri, 22 Feb 2013 20:46:20 +0000 Subject: Note requirements explicitly. --- docs/api-guide/parsers.md | 4 ++++ docs/api-guide/renderers.md | 2 ++ 2 files changed, 6 insertions(+) (limited to 'docs') diff --git a/docs/api-guide/parsers.md b/docs/api-guide/parsers.md index 0cd01639..a2830492 100644 --- a/docs/api-guide/parsers.md +++ b/docs/api-guide/parsers.md @@ -69,6 +69,8 @@ Parses `JSON` request content. Parses `YAML` request content. +Requires the `pyyaml` package to be installed. + **.media_type**: `application/yaml` ## XMLParser @@ -79,6 +81,8 @@ Note that the `XML` markup language is typically used as the base language for m If you are considering using `XML` for your API, you may want to consider implementing a custom renderer and parser for your specific requirements, and using an existing domain-specific media-type, or creating your own custom XML-based media-type. +Requires the `defusedxml` package to be installed. + **.media_type**: `application/xml` ## FormParser diff --git a/docs/api-guide/renderers.md b/docs/api-guide/renderers.md index ca9a6694..5de1491b 100644 --- a/docs/api-guide/renderers.md +++ b/docs/api-guide/renderers.md @@ -90,6 +90,8 @@ The javascript callback function must be set by the client including a `callback Renders the request data into `YAML`. +Requires the `pyyaml` package to be installed. + **.media_type**: `application/yaml` **.format**: `'.yaml'` -- cgit v1.2.3 From d44eb2094211820fbdd014fd2884fd5ed04688ab Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Fri, 22 Feb 2013 20:47:41 +0000 Subject: Version 2.2.1 --- docs/topics/release-notes.md | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'docs') diff --git a/docs/topics/release-notes.md b/docs/topics/release-notes.md index d5444f72..9d29dd27 100644 --- a/docs/topics/release-notes.md +++ b/docs/topics/release-notes.md @@ -40,13 +40,22 @@ You can determine your currently installed version using `pip freeze`: ## 2.2.x series -### Master +### 2.2.1 +**Date**: 22nd Feb 2013 + +* Security fix: Use `defusedxml` package to address XML parsing vulnerabilities. +* Raw data tab added to browseable API. (Eg. Allow for JSON input.) * Added TimeField. -* Serializer fields can be mapped to any method that takes no args, or only takes kwargs which have defaults. +* Serializer fields can be mapped to any method that takes no args, or only takes kwargs which have defaults. +* Unicode support for view names/descriptions in browseable API. * Bugfix: request.DATA should return an empty `QueryDict` with no data, not `None`. * Bugfix: Remove unneeded field validation, which caused extra queries. +**Security note**: Following the [disclosure of security vulnerabilities][defusedxml-announce] in Python's XML parsing libraries, use of the `XMLParser` class now requires the `defusedxml` package to be installed. + +The security vulnerabilities only affect APIs which use the `XMLParser` class, by enabling it in any views, or by having it set in the `DEFAULT_PARSER_CLASSES` setting. Note that the `XMLParser` class is not enabled by default, so this change should affect a minority of users. + ### 2.2.0 **Date**: 13th Feb 2013 @@ -389,6 +398,7 @@ This change will not affect user code, so long as it's following the recommended [cite]: http://www.catb.org/~esr/writings/cathedral-bazaar/cathedral-bazaar/ar01s04.html [deprecation-policy]: #deprecation-policy [django-deprecation-policy]: https://docs.djangoproject.com/en/dev/internals/release-process/#internal-release-deprecation-policy +[defusedxml-announce]: http://blog.python.org/2013/02/announcing-defusedxml-fixes-for-xml.html [2.2-announcement]: 2.2-announcement.md [staticfiles14]: https://docs.djangoproject.com/en/1.4/howto/static-files/#with-a-template-tag [staticfiles13]: https://docs.djangoproject.com/en/1.3/howto/static-files/#with-a-template-tag -- cgit v1.2.3 From d62e4a7aa518b4f0658f8e88fad3f37c95e17082 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Fri, 22 Feb 2013 22:22:37 +0000 Subject: Update release notes --- docs/topics/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'docs') diff --git a/docs/topics/release-notes.md b/docs/topics/release-notes.md index 9d29dd27..22cd3cf0 100644 --- a/docs/topics/release-notes.md +++ b/docs/topics/release-notes.md @@ -40,6 +40,10 @@ You can determine your currently installed version using `pip freeze`: ## 2.2.x series +### Master + +* Bugfixes for model field validation edge-cases. + ### 2.2.1 **Date**: 22nd Feb 2013 -- cgit v1.2.3 From f729506261d241b02b7bacb06cbbe8c0c39980da Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Sat, 23 Feb 2013 07:24:36 +0000 Subject: Update release notes --- docs/topics/release-notes.md | 1 + 1 file changed, 1 insertion(+) (limited to 'docs') diff --git a/docs/topics/release-notes.md b/docs/topics/release-notes.md index 22cd3cf0..06dc79a6 100644 --- a/docs/topics/release-notes.md +++ b/docs/topics/release-notes.md @@ -42,6 +42,7 @@ You can determine your currently installed version using `pip freeze`: ### Master +* Bugfix for serializer data being uncacheable with pickle protocol 0. * Bugfixes for model field validation edge-cases. ### 2.2.1 -- cgit v1.2.3 From 5432f9ba49186f74af568d195cc995a5e75bc046 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Sat, 23 Feb 2013 17:12:40 +0000 Subject: Fill in missing and incorrect settings. --- docs/api-guide/settings.md | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) (limited to 'docs') diff --git a/docs/api-guide/settings.md b/docs/api-guide/settings.md index a422e5f6..e103fbab 100644 --- a/docs/api-guide/settings.md +++ b/docs/api-guide/settings.md @@ -43,7 +43,6 @@ Default: ( 'rest_framework.renderers.JSONRenderer', 'rest_framework.renderers.BrowsableAPIRenderer', - 'rest_framework.renderers.TemplateHTMLRenderer' ) ## DEFAULT_PARSER_CLASSES @@ -54,7 +53,8 @@ Default: ( 'rest_framework.parsers.JSONParser', - 'rest_framework.parsers.FormParser' + 'rest_framework.parsers.FormParser', + 'rest_framework.parsers.MultiPartParser' ) ## DEFAULT_AUTHENTICATION_CLASSES @@ -84,15 +84,21 @@ A list or tuple of throttle classes, that determines the default set of throttle Default: `()` +## DEFAULT_CONTENT_NEGOTIATION_CLASS + +A content negotiation class, that determines how a renderer is selected for the response, given an incoming request. + +Default: `'rest_framework.negotiation.DefaultContentNegotiation'` + ## DEFAULT_MODEL_SERIALIZER_CLASS -**TODO** +A class that determines the default type of model serializer that should be used by a generic view if `model` is specified, but `serializer_class` is not provided. -Default: `rest_framework.serializers.ModelSerializer` +Default: `'rest_framework.serializers.ModelSerializer'` ## DEFAULT_PAGINATION_SERIALIZER_CLASS -**TODO** +A class the determines the default serialization style for paginated responses. Default: `rest_framework.pagination.PaginationSerializer` @@ -158,11 +164,13 @@ Default: `'accept'` ## URL_FORMAT_OVERRIDE +The name of a URL parameter that may be used to override the default `Accept` header based content negotiation. + Default: `'format'` ## FORMAT_SUFFIX_KWARG -**TODO** +The name of a parameter in the URL conf that may be used to provide a format suffix. Default: `'format'` -- cgit v1.2.3 From 41d3fe09cf3dd80cb8efed13dd886645ae7be470 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Sat, 23 Feb 2013 21:29:13 +0000 Subject: Add missing `blank=True` to model in tutorial. --- docs/tutorial/1-serialization.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/tutorial/1-serialization.md b/docs/tutorial/1-serialization.md index 53d24136..691b3500 100644 --- a/docs/tutorial/1-serialization.md +++ b/docs/tutorial/1-serialization.md @@ -86,7 +86,7 @@ For the purposes of this tutorial we're going to start by creating a simple `Sni class Snippet(models.Model): created = models.DateTimeField(auto_now_add=True) - title = models.CharField(max_length=100, default='') + title = models.CharField(max_length=100, blank=True, default='') code = models.TextField() linenos = models.BooleanField(default=False) language = models.CharField(choices=LANGUAGE_CHOICES, -- cgit v1.2.3 From 5b03de8287b04177c30815f5c798fe5c69e0d122 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Sat, 23 Feb 2013 21:29:52 +0000 Subject: Add curl examples. --- docs/tutorial/2-requests-and-responses.md | 36 +++++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-) (limited to 'docs') diff --git a/docs/tutorial/2-requests-and-responses.md b/docs/tutorial/2-requests-and-responses.md index 566c0dc6..63cee3a6 100644 --- a/docs/tutorial/2-requests-and-responses.md +++ b/docs/tutorial/2-requests-and-responses.md @@ -75,11 +75,11 @@ Here is the view for an individual snippet. snippet = Snippet.objects.get(pk=pk) except Snippet.DoesNotExist: return Response(status=status.HTTP_404_NOT_FOUND) - + if request.method == 'GET': serializer = SnippetSerializer(snippet) return Response(serializer.data) - + elif request.method == 'PUT': serializer = SnippetSerializer(snippet, data=request.DATA) if serializer.is_valid(): @@ -126,13 +126,41 @@ We don't necessarily need to add these extra url patterns in, but it gives us a 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** +We can get a list of all of the snippets, as before. + + curl http://127.0.0.1:8000/snippets/ + + [{"id": 1, "title": "", "code": "foo = \"bar\"\n", "linenos": false, "language": "python", "style": "friendly"}, {"id": 2, "title": "", "code": "print \"hello, world\"\n", "linenos": false, "language": "python", "style": "friendly"}] + +We can control the format of the response that we get back, either by using the `Accept` header: + + curl http://127.0.0.1:8000/snippets/ -H 'Accept: application/json' # Request JSON + curl http://127.0.0.1:8000/snippets/ -H 'Accept: text/html' # Request HTML + +Or by appending a format suffix: + + curl http://127.0.0.1:8000/snippets/.json # JSON suffix + curl http://127.0.0.1:8000/snippets/.api # Browseable API suffix + +Similarly, we can control the format of the request that we send, using the `Content-Type` header. + + # POST using form data + curl -X POST http://127.0.0.1:8000/snippets/ -d "code=print 123" + + {"id": 3, "title": "", "code": "123", "linenos": false, "language": "python", "style": "friendly"} + + # POST using JSON + curl -X POST http://127.0.0.1:8000/snippets/ -d '{"code": "print 456"}' -H "Content-Type: application/json" + + {"id": 4, "title": "", "code": "print 456", "linenos": true, "language": "python", "style": "friendly"} Now go and open the API in a web browser, by visiting [http://127.0.0.1:8000/snippets/][devserver]. ### 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. +Because the API chooses the content type of the response based on the client request, it will, by default, return an HTML-formatted representation of the resource when that resource is requested by a web browser. This allows for the API to return a fully web-browsable HTML representation. + +Having a web-browseable API is a huge usability win, and makes developing and using your API much easier. It also dramatically lowers the barrier-to-entry for other developers wanting to inspect and work with your API. See the [browsable api][browseable-api] topic for more information about the browsable API feature and how to customize it. -- cgit v1.2.3 From 9e2131715a40110a5130a1f391de7989b2ed23a9 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Sat, 23 Feb 2013 21:52:26 +0000 Subject: Formatting. --- docs/tutorial/1-serialization.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'docs') diff --git a/docs/tutorial/1-serialization.md b/docs/tutorial/1-serialization.md index 691b3500..6709f751 100644 --- a/docs/tutorial/1-serialization.md +++ b/docs/tutorial/1-serialization.md @@ -304,11 +304,11 @@ It's worth noting that there are a couple of edge cases we're not dealing with p Now we can start up a sample server that serves our snippets. -Quit out of the shell +Quit out of the shell... quit() -and start up Django's development server +...and start up Django's development server. python manage.py runserver @@ -327,7 +327,7 @@ We can get a list of all of the snippets. [{"id": 1, "title": "", "code": "foo = \"bar\"\n", "linenos": false, "language": "python", "style": "friendly"}, {"id": 2, "title": "", "code": "print \"hello, world\"\n", "linenos": false, "language": "python", "style": "friendly"}] -or we can get a particular snippet by referencing its id +Or we can get a particular snippet by referencing its id. curl http://127.0.0.1:8000/snippets/2/ -- cgit v1.2.3 From 4a80dff1efee238ef789a2f90ba150d05566d3e2 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Sat, 23 Feb 2013 21:52:46 +0000 Subject: Autenticating with curl example. --- docs/tutorial/4-authentication-and-permissions.md | 25 +++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) (limited to 'docs') diff --git a/docs/tutorial/4-authentication-and-permissions.md b/docs/tutorial/4-authentication-and-permissions.md index 282386c7..f295aeb6 100644 --- a/docs/tutorial/4-authentication-and-permissions.md +++ b/docs/tutorial/4-authentication-and-permissions.md @@ -104,8 +104,6 @@ This field is doing something quite interesting. The `source` argument controls The field we've added is the untyped `Field` class, in contrast to the other typed fields, such as `CharField`, `BooleanField` etc... The untyped `Field` is always read-only, and will be used for serialized representations, but will not be used for updating model instances when they are deserialized. -**TODO: Explain the SessionAuthentication and BasicAuthentication classes, and demonstrate using HTTP basic authentication with curl requests** - ## Adding required permissions to views Now that code snippets are associated with users, we want to make sure that only authenticated users are able to create, update and delete code snippets. @@ -120,8 +118,6 @@ Then, add the following property to **both** the `SnippetList` and `SnippetDetai permission_classes = (permissions.IsAuthenticatedOrReadOnly,) -**TODO: Now that the permissions are restricted, demonstrate using HTTP basic authentication with curl requests** - ## Adding login to the Browseable API If you open a browser and navigate to the browseable API at the moment, you'll find that you're no longer able to create new code snippets. In order to do so we'd need to be able to login as a user. @@ -181,10 +177,31 @@ Make sure to also import the `IsOwnerOrReadOnly` class. Now, if you open a browser again, you find that the 'DELETE' and 'PUT' actions only appear on a snippet instance endpoint if you're logged in as the same user that created the code snippet. +## Authenticating with the API + +Because we now have a set of permissions on the API, we need to authenticate our requests to it if we want to edit any snippets. We havn't set up any [authentication classes][authentication], so the defaults are currently applied, which are `SessionAuthentication` and `BasicAuthentication`. + +When we interact with the API through the web browser, we can login, and the browser session will then provide the required authentication for the requests. + +If we're interacting with the API programmatically we need to explicitly provide the authentication credentials on each request. + +If we try to create a snippet without authenticating, we'll get an error: + + curl -i -X POST http://127.0.0.1:8000/snippets/ -d "code=print 123" + + {"detail": "Authentication credentials were not provided."} + +We can make a successful request by including the username and password of one of the users we created earlier. + + curl -X POST http://127.0.0.1:8000/snippets/ -d "code=print 789" -u tom:password + + {"url": "http://127.0.0.1:8000/snippets/5/", "highlight": "http://127.0.0.1:8000/snippets/5/highlight/", "owner": "tom", "title": "foo", "code": "print 789", "linenos": false, "language": "python", "style": "friendly"} + ## Summary We've now got a fairly fine-grained set of permissions on our Web API, and end points for users of the system and for the code snippets that they have created. In [part 5][tut-5] of the tutorial we'll look at how we can tie everything together by creating an HTML endpoint for our hightlighted snippets, and improve the cohesion of our API by using hyperlinking for the relationships within the system. +[authentication]: ../api-guide/authentication.md [tut-5]: 5-relationships-and-hyperlinked-apis.md -- cgit v1.2.3 From ca8e073e34c3fa38b35b93a598cae76506ed626d Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Sat, 23 Feb 2013 22:01:29 +0000 Subject: TODO -> TODONE --- docs/api-guide/serializers.md | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) (limited to 'docs') diff --git a/docs/api-guide/serializers.md b/docs/api-guide/serializers.md index 85189434..6f1f2883 100644 --- a/docs/api-guide/serializers.md +++ b/docs/api-guide/serializers.md @@ -228,15 +228,17 @@ The `ModelSerializer` class lets you automatically create a Serializer class wit class Meta: model = Account -**[TODO: Explain model field to serializer field mapping in more detail]** +By default, all the model fields on the class will be mapped to corresponding serializer fields. + +Any foreign keys on the model will be mapped to `PrimaryKeyRelatedField` if you're using a `ModelSerializer`, or `HyperlinkedRelatedField` if you're using a `HyperlinkedModelSerializer`. ## Specifying fields explicitly You can add extra fields to a `ModelSerializer` or override the default fields by declaring fields on the class, just as you would for a `Serializer` class. class AccountSerializer(serializers.ModelSerializer): - url = CharField(source='get_absolute_url', read_only=True) - group = NaturalKeyField() + url = serializers.CharField(source='get_absolute_url', read_only=True) + groups = serializers.PrimaryKeyRelatedField(many=True) class Meta: model = Account @@ -245,17 +247,11 @@ Extra fields can correspond to any property or callable on the model. ## Relational fields -When serializing model instances, there are a number of different ways you might choose to represent relationships. The default representation is to use the primary keys of the related instances. - -Alternative representations include serializing using natural keys, serializing complete nested representations, or serializing using a custom representation, such as a URL that uniquely identifies the model instances. - -The `PrimaryKeyRelatedField` and `HyperlinkedRelatedField` fields provide alternative flat representations. - -The `ModelSerializer` class can itself be used as a field, in order to serialize relationships using nested representations. +When serializing model instances, there are a number of different ways you might choose to represent relationships. The default representation for `ModelSerializer` is to use the primary keys of the related instances. -The `RelatedField` class may be subclassed to create a custom representation of a relationship. The subclass should override `.to_native()`, and optionally `.from_native()` if deserialization is supported. +Alternative representations include serializing using hyperlinks, serializing complete nested representations, or serializing with a custom representation. -All the relational fields may be used for any relationship or reverse relationship on a model. +For full details see the [serializer relations][relations] documentation. ## Specifying which fields should be included @@ -330,3 +326,4 @@ The following custom model serializer could be used as a base class for model se [cite]: https://groups.google.com/d/topic/django-users/sVFaOfQi4wY/discussion +[relations]: relations.md -- cgit v1.2.3 From ea7d73f57e4cb69d5321188e33019c7ab3b89d8e Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Sat, 23 Feb 2013 22:07:33 +0000 Subject: Spelling. --- docs/tutorial/4-authentication-and-permissions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/tutorial/4-authentication-and-permissions.md b/docs/tutorial/4-authentication-and-permissions.md index f295aeb6..9ac9deac 100644 --- a/docs/tutorial/4-authentication-and-permissions.md +++ b/docs/tutorial/4-authentication-and-permissions.md @@ -201,7 +201,7 @@ We can make a successful request by including the username and password of one o We've now got a fairly fine-grained set of permissions on our Web API, and end points for users of the system and for the code snippets that they have created. -In [part 5][tut-5] of the tutorial we'll look at how we can tie everything together by creating an HTML endpoint for our hightlighted snippets, and improve the cohesion of our API by using hyperlinking for the relationships within the system. +In [part 5][tut-5] of the tutorial we'll look at how we can tie everything together by creating an HTML endpoint for our highlighted snippets, and improve the cohesion of our API by using hyperlinking for the relationships within the system. [authentication]: ../api-guide/authentication.md [tut-5]: 5-relationships-and-hyperlinked-apis.md -- cgit v1.2.3 From 4599cd97cbbfd2f569408cbadef3a3753d19f406 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Sat, 23 Feb 2013 22:13:06 +0000 Subject: Fix curl response. Didn't map to the correct stage of the tutorial. --- docs/tutorial/4-authentication-and-permissions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/tutorial/4-authentication-and-permissions.md b/docs/tutorial/4-authentication-and-permissions.md index 9ac9deac..3c4e042b 100644 --- a/docs/tutorial/4-authentication-and-permissions.md +++ b/docs/tutorial/4-authentication-and-permissions.md @@ -195,7 +195,7 @@ We can make a successful request by including the username and password of one o curl -X POST http://127.0.0.1:8000/snippets/ -d "code=print 789" -u tom:password - {"url": "http://127.0.0.1:8000/snippets/5/", "highlight": "http://127.0.0.1:8000/snippets/5/highlight/", "owner": "tom", "title": "foo", "code": "print 789", "linenos": false, "language": "python", "style": "friendly"} + {"id": 5, "owner": "tom", "title": "foo", "code": "print 789", "linenos": false, "language": "python", "style": "friendly"} ## Summary -- cgit v1.2.3 From cd9a192027bbbe231a25cca4b46d56f520b42de7 Mon Sep 17 00:00:00 2001 From: Ryan Detzel Date: Sat, 23 Feb 2013 23:32:47 +0100 Subject: method fix for custom authentication --- docs/api-guide/authentication.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/api-guide/authentication.md b/docs/api-guide/authentication.md index 8c1d1185..342fabe7 100644 --- a/docs/api-guide/authentication.md +++ b/docs/api-guide/authentication.md @@ -202,7 +202,7 @@ If the `.authenticate_header()` method is not overridden, the authentication sch The following example will authenticate any incoming request as the user given by the username in a custom request header named 'X_USERNAME'. class ExampleAuthentication(authentication.BaseAuthentication): - def has_permission(self, request, view, obj=None): + def authenticate(self, request): username = request.META.get('X_USERNAME') if not username: return None -- cgit v1.2.3 From b4b9d3b513074810abcbc52e7eaa21616fba26d5 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Mon, 25 Feb 2013 13:44:32 +0000 Subject: Added @ryanrdetzel for docs fix #674. 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 e546548e..e544c9c8 100644 --- a/docs/topics/credits.md +++ b/docs/topics/credits.md @@ -104,6 +104,7 @@ The following people have helped make REST framework great. * Xavier Ordoquy - [xordoquy] * Adam Wentz - [floppya] * Andreas Pelme - [pelme] +* Ryan Detzel - [ryanrdetzel] Many thanks to everyone who's contributed to the project. @@ -242,3 +243,4 @@ You can also contact [@_tomchristie][twitter] directly on twitter. [xordoquy]: https://github.com/xordoquy [floppya]: https://github.com/floppya [pelme]: https://github.com/pelme +[ryanrdetzel]: https://github.com/ryanrdetzel -- cgit v1.2.3 From 8da83f0df9761550cbcac88850a659aab00a2506 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Mon, 25 Feb 2013 15:15:33 +0000 Subject: Added @thedrow for cleanups in #677. 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 e544c9c8..00513504 100644 --- a/docs/topics/credits.md +++ b/docs/topics/credits.md @@ -105,6 +105,7 @@ The following people have helped make REST framework great. * Adam Wentz - [floppya] * Andreas Pelme - [pelme] * Ryan Detzel - [ryanrdetzel] +* Omer Katz - [thedrow] Many thanks to everyone who's contributed to the project. @@ -244,3 +245,4 @@ You can also contact [@_tomchristie][twitter] directly on twitter. [floppya]: https://github.com/floppya [pelme]: https://github.com/pelme [ryanrdetzel]: https://github.com/ryanrdetzel +[thedrow]: https://github.com/thedrow -- cgit v1.2.3 From 5d9ed34e4115f683294082faf9c9584a53bb7e49 Mon Sep 17 00:00:00 2001 From: swistakm Date: Mon, 25 Feb 2013 17:41:34 +0100 Subject: add OAuthAuthentication documentation stub --- docs/api-guide/authentication.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'docs') diff --git a/docs/api-guide/authentication.md b/docs/api-guide/authentication.md index 8c1d1185..81b35909 100644 --- a/docs/api-guide/authentication.md +++ b/docs/api-guide/authentication.md @@ -182,6 +182,20 @@ Unauthenticated responses that are denied permission will result in an `HTTP 403 If you're using an AJAX style API with SessionAuthentication, you'll need to make sure you include a valid CSRF token for any "unsafe" HTTP method calls, such as `PUT`, `PATCH`, `POST` or `DELETE` requests. See the [Django CSRF documentation][csrf-ajax] for more details. +## OAuthAuthentication + +This authentication uses [OAuth 1.0](http://tools.ietf.org/html/rfc5849) authentication scheme. It depends on optional `django-oauth-plus` and `oauth2` packages. In order to make it work you must istall these packages and add `oauth_provider` (from `django-oauth-plus`) to your `INSTALLED_APPS`: + + INSTALLED_APPS = ( + #(...) + `oauth_provider`, + ) + +OAuthAuthentication class provides only token verification and signature validation for requests. It doesn't provide authorization flow for your clients. You still need to implement your own views for accessing and authorizing Reqest/Access Tokens. This is because there are many different OAuth flows in use. Almost always they require end-user interaction, and most likely this is what you want to design yourself. + +Luckily `django-oauth-plus` provides simple foundation for classic 'three-legged' oauth flow, so if it is what you need please refer to [its documentation](http://code.larlet.fr/django-oauth-plus/wiki/Home). This documentation will provide you also information about how to work with supplied models and change basic settings. + + # Custom authentication To implement a custom authentication scheme, subclass `BaseAuthentication` and override the `.authenticate(self, request)` method. The method should return a two-tuple of `(user, auth)` if authentication succeeds, or `None` otherwise. -- cgit v1.2.3 From 70db39859586aa49b6065ee1625fbfba3b50ae23 Mon Sep 17 00:00:00 2001 From: Danilo Bargen Date: Mon, 25 Feb 2013 21:31:12 +0100 Subject: Renamed UserInstance to UserDetail in docs --- docs/api-guide/renderers.md | 4 ++-- docs/tutorial/4-authentication-and-permissions.md | 4 ++-- docs/tutorial/5-relationships-and-hyperlinked-apis.md | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'docs') diff --git a/docs/api-guide/renderers.md b/docs/api-guide/renderers.md index 5de1491b..3c8396aa 100644 --- a/docs/api-guide/renderers.md +++ b/docs/api-guide/renderers.md @@ -123,7 +123,7 @@ The template name is determined by (in order of preference): An example of a view that uses `TemplateHTMLRenderer`: - class UserInstance(generics.RetrieveUserAPIView): + class UserDetail(generics.RetrieveUserAPIView): """ A view that returns a templated HTML representations of a given user. """ @@ -301,4 +301,4 @@ Comma-separated values are a plain-text tabular data format, that can be easily [juanriaza]: https://github.com/juanriaza [mjumbewu]: https://github.com/mjumbewu [djangorestframework-msgpack]: https://github.com/juanriaza/django-rest-framework-msgpack -[djangorestframework-csv]: https://github.com/mjumbewu/django-rest-framework-csv \ No newline at end of file +[djangorestframework-csv]: https://github.com/mjumbewu/django-rest-framework-csv diff --git a/docs/tutorial/4-authentication-and-permissions.md b/docs/tutorial/4-authentication-and-permissions.md index 3c4e042b..3ee755a2 100644 --- a/docs/tutorial/4-authentication-and-permissions.md +++ b/docs/tutorial/4-authentication-and-permissions.md @@ -72,14 +72,14 @@ We'll also add a couple of views. We'd like to just use read-only views for the serializer_class = UserSerializer - class UserInstance(generics.RetrieveAPIView): + class UserDetail(generics.RetrieveAPIView): model = User serializer_class = UserSerializer Finally we need to add those views into the API, by referencing them from the URL conf. url(r'^users/$', views.UserList.as_view()), - url(r'^users/(?P[0-9]+)/$', views.UserInstance.as_view()), + url(r'^users/(?P[0-9]+)/$', views.UserDetail.as_view()), ## Associating Snippets with Users diff --git a/docs/tutorial/5-relationships-and-hyperlinked-apis.md b/docs/tutorial/5-relationships-and-hyperlinked-apis.md index 81be333b..a702a09d 100644 --- a/docs/tutorial/5-relationships-and-hyperlinked-apis.md +++ b/docs/tutorial/5-relationships-and-hyperlinked-apis.md @@ -123,7 +123,7 @@ After adding all those names into our URLconf, our final `'urls.py'` file should views.UserList.as_view(), name='user-list'), url(r'^users/(?P[0-9]+)/$', - views.UserInstance.as_view(), + views.UserDetail.as_view(), name='user-detail') )) @@ -173,4 +173,4 @@ We've reached the end of our tutorial. If you want to get more involved in the [sandbox]: http://restframework.herokuapp.com/ [github]: https://github.com/tomchristie/django-rest-framework [group]: https://groups.google.com/forum/?fromgroups#!forum/django-rest-framework -[twitter]: https://twitter.com/_tomchristie \ No newline at end of file +[twitter]: https://twitter.com/_tomchristie -- cgit v1.2.3 From bfdbc95f1a616da952da77cac31cd223a5554814 Mon Sep 17 00:00:00 2001 From: Danilo Bargen Date: Tue, 26 Feb 2013 10:30:42 +0100 Subject: Added CBV example to format-suffixes docs --- docs/api-guide/format-suffixes.md | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'docs') diff --git a/docs/api-guide/format-suffixes.md b/docs/api-guide/format-suffixes.md index 6d5feba4..02fa1810 100644 --- a/docs/api-guide/format-suffixes.md +++ b/docs/api-guide/format-suffixes.md @@ -35,12 +35,22 @@ Example: urlpatterns = format_suffix_patterns(urlpatterns, allowed=['json', 'html']) -When using `format_suffix_patterns`, you must make sure to add the `'format'` keyword argument to the corresponding views. For example. +When using `format_suffix_patterns`, you must make sure to add the `'format'` keyword argument to the corresponding view. For example: @api_view(('GET',)) def api_root(request, format=None): # do stuff... +Or with class based views: + + class CommentList(APIView): + + def get(self, request, format=None): + # do stuff... + + def post(self, request, format=None): + # do stuff... + The name of the kwarg used may be modified by using the `FORMAT_SUFFIX_KWARG` setting. Also note that `format_suffix_patterns` does not support descending into `include` URL patterns. @@ -58,4 +68,4 @@ It is actually a misconception. For example, take the following quote from Roy The quote does not mention Accept headers, but it does make it clear that format suffixes should be considered an acceptable pattern. [cite]: http://tech.groups.yahoo.com/group/rest-discuss/message/5857 -[cite2]: http://tech.groups.yahoo.com/group/rest-discuss/message/14844 \ No newline at end of file +[cite2]: http://tech.groups.yahoo.com/group/rest-discuss/message/14844 -- cgit v1.2.3 From cd7f552540778a744f51ade76aa4f8067eaf303a Mon Sep 17 00:00:00 2001 From: Wiliam Souza Date: Tue, 26 Feb 2013 10:43:33 -0300 Subject: Fixed a typo WritableField field name in docs --- docs/api-guide/fields.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/api-guide/fields.md b/docs/api-guide/fields.md index 8c28273b..d7f9197f 100644 --- a/docs/api-guide/fields.md +++ b/docs/api-guide/fields.md @@ -102,7 +102,7 @@ You can customize this behavior by overriding the `.to_native(self, value)` met ## WritableField -A field that supports both read and write operations. By itself `WriteableField` does not perform any translation of input values into a given type. You won't typically use this field directly, but you may want to override it and implement the `.to_native(self, value)` and `.from_native(self, value)` methods. +A field that supports both read and write operations. By itself `WritableField` does not perform any translation of input values into a given type. You won't typically use this field directly, but you may want to override it and implement the `.to_native(self, value)` and `.from_native(self, value)` methods. ## ModelField -- cgit v1.2.3 From 80b0234793321f828979d30015151c8d7900fc9f Mon Sep 17 00:00:00 2001 From: Stephan Groß Date: Tue, 26 Feb 2013 14:50:10 +0100 Subject: Add @waa for #687 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 00513504..d1bb907a 100644 --- a/docs/topics/credits.md +++ b/docs/topics/credits.md @@ -106,6 +106,7 @@ The following people have helped make REST framework great. * Andreas Pelme - [pelme] * Ryan Detzel - [ryanrdetzel] * Omer Katz - [thedrow] +* Wiliam Souza - [waa] Many thanks to everyone who's contributed to the project. @@ -246,3 +247,4 @@ You can also contact [@_tomchristie][twitter] directly on twitter. [pelme]: https://github.com/pelme [ryanrdetzel]: https://github.com/ryanrdetzel [thedrow]: https://github.com/thedrow +[waa]: https://github.com/wiliamsouza -- cgit v1.2.3 From e7ca326555b02e1f415469c83495f99c22ea1a0f Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Tue, 26 Feb 2013 19:51:09 +0000 Subject: Tweaks --- docs/api-guide/format-suffixes.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'docs') diff --git a/docs/api-guide/format-suffixes.md b/docs/api-guide/format-suffixes.md index 02fa1810..53e5f2bf 100644 --- a/docs/api-guide/format-suffixes.md +++ b/docs/api-guide/format-suffixes.md @@ -35,9 +35,9 @@ Example: urlpatterns = format_suffix_patterns(urlpatterns, allowed=['json', 'html']) -When using `format_suffix_patterns`, you must make sure to add the `'format'` keyword argument to the corresponding view. For example: +When using `format_suffix_patterns`, you must make sure to add the `'format'` keyword argument to the corresponding views. For example: - @api_view(('GET',)) + @api_view(('GET', 'POST')) def api_root(request, format=None): # do stuff... -- cgit v1.2.3 From 35331f5820cff9a5cd97ccff2c1cbbb8a5a62790 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Tue, 26 Feb 2013 19:54:04 +0000 Subject: More consistent examples --- docs/api-guide/format-suffixes.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'docs') diff --git a/docs/api-guide/format-suffixes.md b/docs/api-guide/format-suffixes.md index 53e5f2bf..d63efc9c 100644 --- a/docs/api-guide/format-suffixes.md +++ b/docs/api-guide/format-suffixes.md @@ -29,8 +29,8 @@ Example: urlpatterns = patterns('blog.views', url(r'^/$', 'api_root'), - url(r'^comment/$', 'comment_root'), - url(r'^comment/(?P[0-9]+)/$', 'comment_instance') + url(r'^comment/$', 'comment_list'), + url(r'^comment/(?P[0-9]+)/$', 'comment_detail') ) urlpatterns = format_suffix_patterns(urlpatterns, allowed=['json', 'html']) @@ -38,13 +38,12 @@ Example: When using `format_suffix_patterns`, you must make sure to add the `'format'` keyword argument to the corresponding views. For example: @api_view(('GET', 'POST')) - def api_root(request, format=None): + def comment_list(request, format=None): # do stuff... Or with class based views: class CommentList(APIView): - def get(self, request, format=None): # do stuff... -- cgit v1.2.3 From 2eabc5c2b46d9f4cc7a467af849ff31397b9d7bf Mon Sep 17 00:00:00 2001 From: swistakm Date: Wed, 27 Feb 2013 11:02:50 +0100 Subject: rfc5849 link with anchor --- docs/api-guide/authentication.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/api-guide/authentication.md b/docs/api-guide/authentication.md index 81b35909..d7918e10 100644 --- a/docs/api-guide/authentication.md +++ b/docs/api-guide/authentication.md @@ -184,7 +184,7 @@ If you're using an AJAX style API with SessionAuthentication, you'll need to mak ## OAuthAuthentication -This authentication uses [OAuth 1.0](http://tools.ietf.org/html/rfc5849) authentication scheme. It depends on optional `django-oauth-plus` and `oauth2` packages. In order to make it work you must istall these packages and add `oauth_provider` (from `django-oauth-plus`) to your `INSTALLED_APPS`: +This authentication uses [OAuth 1.0][rfc5849] authentication scheme. It depends on optional `django-oauth-plus` and `oauth2` packages. In order to make it work you must istall these packages and add `oauth_provider` (from `django-oauth-plus`) to your `INSTALLED_APPS`: INSTALLED_APPS = ( #(...) @@ -249,3 +249,4 @@ HTTP digest authentication is a widely implemented scheme that was intended to r [mod_wsgi_official]: http://code.google.com/p/modwsgi/wiki/ConfigurationDirectives#WSGIPassAuthorization [juanriaza]: https://github.com/juanriaza [djangorestframework-digestauth]: https://github.com/juanriaza/django-rest-framework-digestauth +[rfc5849] : http://tools.ietf.org/html/rfc5849 \ No newline at end of file -- cgit v1.2.3 From 27aa2d6aad59c479de66e270b897c4fa4fdbac30 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Wed, 27 Feb 2013 22:13:24 +0000 Subject: Use plularized URLs for better consistency. Closes #684. --- docs/api-guide/format-suffixes.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'docs') diff --git a/docs/api-guide/format-suffixes.md b/docs/api-guide/format-suffixes.md index d63efc9c..dae3dea3 100644 --- a/docs/api-guide/format-suffixes.md +++ b/docs/api-guide/format-suffixes.md @@ -29,8 +29,8 @@ Example: urlpatterns = patterns('blog.views', url(r'^/$', 'api_root'), - url(r'^comment/$', 'comment_list'), - url(r'^comment/(?P[0-9]+)/$', 'comment_detail') + url(r'^comments/$', 'comment_list'), + url(r'^comments/(?P[0-9]+)/$', 'comment_detail') ) urlpatterns = format_suffix_patterns(urlpatterns, allowed=['json', 'html']) -- cgit v1.2.3 From 13b3af0d22bdbae5be0eb39ea50219c1fb83e28f Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Thu, 28 Feb 2013 17:58:58 +0000 Subject: Auth is no longer lazy. Closes #667. More consistent auth failure behavior. --- docs/api-guide/authentication.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'docs') diff --git a/docs/api-guide/authentication.md b/docs/api-guide/authentication.md index 342fabe7..fae86386 100644 --- a/docs/api-guide/authentication.md +++ b/docs/api-guide/authentication.md @@ -10,7 +10,7 @@ Authentication is the mechanism of associating an incoming request with a set of REST framework provides a number of authentication schemes out of the box, and also allows you to implement custom schemes. -Authentication will run the first time either the `request.user` or `request.auth` properties are accessed, and determines how those properties are initialized. +Authentication is always run at the very start of the view, before the permission and throttling checks occur, and before any other code is allowed to proceed. The `request.user` property will typically be set to an instance of the `contrib.auth` package's `User` class. @@ -191,7 +191,7 @@ In some circumstances instead of returning `None`, you may want to raise an `Aut Typically the approach you should take is: * If authentication is not attempted, return `None`. Any other authentication schemes also in use will still be checked. -* If authentication is attempted but fails, raise a `AuthenticationFailed` exception. An error response will be returned immediately, without checking any other authentication schemes. +* If authentication is attempted but fails, raise a `AuthenticationFailed` exception. An error response will be returned immediately, regardless of any permissions checks, and without checking any other authentication schemes. You *may* also override the `.authenticate_header(self, request)` method. If implemented, it should return a string that will be used as the value of the `WWW-Authenticate` header in a `HTTP 401 Unauthorized` response. -- cgit v1.2.3 From 282af6057f30b5af4665d687200ee1ebf82fcf00 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Thu, 28 Feb 2013 18:02:10 +0000 Subject: Release notes --- docs/topics/release-notes.md | 1 + 1 file changed, 1 insertion(+) (limited to 'docs') diff --git a/docs/topics/release-notes.md b/docs/topics/release-notes.md index 06dc79a6..43499c9a 100644 --- a/docs/topics/release-notes.md +++ b/docs/topics/release-notes.md @@ -42,6 +42,7 @@ You can determine your currently installed version using `pip freeze`: ### Master +* Request authentication is no longer lazily evaluated, instead authentication is always run, which results in more consistent, obvious behavior. Eg. Supplying bad auth credentials will now always return an error response, even if no permissions are set on the view. * Bugfix for serializer data being uncacheable with pickle protocol 0. * Bugfixes for model field validation edge-cases. -- cgit v1.2.3 From d8f455bc0ff920e9e0cd1952f58b5a0eccdc2683 Mon Sep 17 00:00:00 2001 From: Pierre Dulac Date: Fri, 1 Mar 2013 02:09:52 +0100 Subject: Add OAuth2Authentication documentation --- docs/api-guide/authentication.md | 69 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) (limited to 'docs') diff --git a/docs/api-guide/authentication.md b/docs/api-guide/authentication.md index 342fabe7..ba7c0c58 100644 --- a/docs/api-guide/authentication.md +++ b/docs/api-guide/authentication.md @@ -182,6 +182,74 @@ Unauthenticated responses that are denied permission will result in an `HTTP 403 If you're using an AJAX style API with SessionAuthentication, you'll need to make sure you include a valid CSRF token for any "unsafe" HTTP method calls, such as `PUT`, `PATCH`, `POST` or `DELETE` requests. See the [Django CSRF documentation][csrf-ajax] for more details. +## OAuth2Authentication + +This authentication uses [OAuth 2.0][rfc6749] authentication scheme. It depends on optional [`django-oauth2-provider`](https://github.com/caffeinehit/django-oauth2-provider). In order to make it work you must install this package and add `provider` and `provider.oauth2` to your `INSTALLED_APPS` : + + INSTALLED_APPS = ( + #(...) + 'provider', + 'provider.oauth2', + ) + +And include the urls needed in your root `urls.py` file to be able to begin the *oauth 2 dance* : + + url(r'^oauth2/', include('provider.oauth2.urls', namespace = 'oauth2')), + +--- + +** Note:** The *namespace* argument is required ! + +--- + +Finally, sync your database with those two new django apps. + + $ python manage.py syncdb + $ python manage.py migrate + +`OAuth2Authentication` class provides only token verification for requests. The *oauth 2 dance* is taken care by the [`django-oaut2-provider`](https://github.com/caffeinehit/django-oauth2-provider) dependency. Unfortunately, there isn't a lot of [documentation](https://django-oauth2-provider.readthedocs.org/en/latest/) currently on how to *dance* with this package on the client side. + +The Good news is, here is a minimal "How to start" because **OAuth 2** is dramatically simpler than **OAuth 1**, so no more headache with signature, cryptography on client side, and other complex things. + +### How to start with *django-oauth2-provider* ? + +#### Create a client in the django-admin panel + +Go to the admin panel and create a new `Provider.Client` entry. It will create the `client_id` and `client_secret` properties for you. + +#### Request an access token + +Your client interface – I mean by that your iOS code, HTML code, or whatever else language – just have to submit a `POST` request at the url `/oauth2/access_token` with the following fields : + +* `client_id` the client id you've just configured at the previous step. +* `client_secret` again configured at the previous step. +* `username` the username with which you want to log in. +* `password` well, that speaks for itself. + +--- + +**Note:** Remember that you are **highly encourage** to use HTTPS for all your OAuth 2 requests. And by *highly encourage* I mean you SHOULD always use HTTPS otherwise you will expose user passwords for any person who can intercept the request (like a man in the middle attack). + +--- + +You can use the command line to test that your local configuration is working : + + $ curl -X POST -d "client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET&grant_type=password&username=YOUR_USERNAME&password=YOU_PASSWORD" http://localhost:8000/oauth2/access_token/ + +Here is the response you should get : + + {"access_token": "", "scope": "read", "expires_in": 86399, "refresh_token": ""} + +#### Access the api + +The only thing needed to make the `OAuth2Authentication` class work is to insert the `access_token` you've received in the `Authorization` api request header. + +The command line to test the authentication looks like : + + $ curl -H "Authorization: Bearer " http://localhost:8000/api/?client_id=YOUR_CLIENT_ID\&client_secret=YOUR_CLIENT_SECRET + +And hopefully, it will work like a charm. + # Custom authentication To implement a custom authentication scheme, subclass `BaseAuthentication` and override the `.authenticate(self, request)` method. The method should return a two-tuple of `(user, auth)` if authentication succeeds, or `None` otherwise. @@ -235,3 +303,4 @@ HTTP digest authentication is a widely implemented scheme that was intended to r [mod_wsgi_official]: http://code.google.com/p/modwsgi/wiki/ConfigurationDirectives#WSGIPassAuthorization [juanriaza]: https://github.com/juanriaza [djangorestframework-digestauth]: https://github.com/juanriaza/django-rest-framework-digestauth +[rfc6749]: http://tools.ietf.org/html/rfc6749 -- cgit v1.2.3 From 653fcf7e3315f9aefba8474591909e564492ecfe Mon Sep 17 00:00:00 2001 From: Pierre Dulac Date: Fri, 1 Mar 2013 12:02:03 +0100 Subject: Use the correct doc link style --- docs/api-guide/authentication.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'docs') diff --git a/docs/api-guide/authentication.md b/docs/api-guide/authentication.md index 6a259500..c73de1f6 100644 --- a/docs/api-guide/authentication.md +++ b/docs/api-guide/authentication.md @@ -184,7 +184,7 @@ If you're using an AJAX style API with SessionAuthentication, you'll need to mak ## OAuth2Authentication -This authentication uses [OAuth 2.0][rfc6749] authentication scheme. It depends on optional [`django-oauth2-provider`](https://github.com/caffeinehit/django-oauth2-provider). In order to make it work you must install this package and add `provider` and `provider.oauth2` to your `INSTALLED_APPS` : +This authentication uses [OAuth 2.0][rfc6749] authentication scheme. It depends on optional [`django-oauth2-provider`][django-oauth2-provider]. In order to make it work you must install this package and add `provider` and `provider.oauth2` to your `INSTALLED_APPS` : INSTALLED_APPS = ( #(...) @@ -207,7 +207,7 @@ Finally, sync your database with those two new django apps. $ python manage.py syncdb $ python manage.py migrate -`OAuth2Authentication` class provides only token verification for requests. The *oauth 2 dance* is taken care by the [`django-oaut2-provider`](https://github.com/caffeinehit/django-oauth2-provider) dependency. Unfortunately, there isn't a lot of [documentation](https://django-oauth2-provider.readthedocs.org/en/latest/) currently on how to *dance* with this package on the client side. +`OAuth2Authentication` class provides only token verification for requests. The *oauth 2 dance* is taken care by the [`django-oaut2-provider`][django-oauth2-provider] dependency. Unfortunately, there isn't a lot of [documentation][django-oauth2-provider--doc] currently on how to *dance* with this package on the client side. The Good news is, here is a minimal "How to start" because **OAuth 2** is dramatically simpler than **OAuth 1**, so no more headache with signature, cryptography on client side, and other complex things. @@ -303,4 +303,6 @@ HTTP digest authentication is a widely implemented scheme that was intended to r [mod_wsgi_official]: http://code.google.com/p/modwsgi/wiki/ConfigurationDirectives#WSGIPassAuthorization [juanriaza]: https://github.com/juanriaza [djangorestframework-digestauth]: https://github.com/juanriaza/django-rest-framework-digestauth +[django-oauth2-provider]: https://github.com/caffeinehit/django-oauth2-provider +[django-oauth2-provider--doc]: https://django-oauth2-provider.readthedocs.org/en/latest/ [rfc6749]: http://tools.ietf.org/html/rfc6749 -- cgit v1.2.3 From 9157db5da0b5601793d1a9f24e9cb10670a82be2 Mon Sep 17 00:00:00 2001 From: Stephan Groß Date: Tue, 26 Feb 2013 11:09:54 +0100 Subject: Add better date / datetime validation (pull 2) addition to #631 with update to master + timefield support --- docs/api-guide/fields.md | 12 ++++++++++++ docs/topics/release-notes.md | 3 +++ 2 files changed, 15 insertions(+) (limited to 'docs') diff --git a/docs/api-guide/fields.md b/docs/api-guide/fields.md index d7f9197f..abacc1b8 100644 --- a/docs/api-guide/fields.md +++ b/docs/api-guide/fields.md @@ -185,12 +185,20 @@ Corresponds to `django.forms.fields.RegexField` A date representation. +Uses `DATE_INPUT_FORMATS` to validate date. + +Optionally takes `format` as parameter to replace the matching pattern. + Corresponds to `django.db.models.fields.DateField` ## DateTimeField A date and time representation. +Uses `DATETIME_INPUT_FORMATS` to validate date_time. + +Optionally takes `format` as parameter to replace the matching pattern. + Corresponds to `django.db.models.fields.DateTimeField` When using `ModelSerializer` or `HyperlinkedModelSerializer`, note that any model fields with `auto_now=True` or `auto_now_add=True` will use serializer fields that are `read_only=True` by default. @@ -207,6 +215,10 @@ If you want to override this behavior, you'll need to declare the `DateTimeField A time representation. +Uses `TIME_INPUT_FORMATS` to validate time. + +Optionally takes `format` as parameter to replace the matching pattern. + Corresponds to `django.db.models.fields.TimeField` ## IntegerField diff --git a/docs/topics/release-notes.md b/docs/topics/release-notes.md index 43499c9a..f60382ac 100644 --- a/docs/topics/release-notes.md +++ b/docs/topics/release-notes.md @@ -45,6 +45,9 @@ You can determine your currently installed version using `pip freeze`: * Request authentication is no longer lazily evaluated, instead authentication is always run, which results in more consistent, obvious behavior. Eg. Supplying bad auth credentials will now always return an error response, even if no permissions are set on the view. * Bugfix for serializer data being uncacheable with pickle protocol 0. * Bugfixes for model field validation edge-cases. +* Support `DATE_INPUT_FORMATS` for `DateField` validation +* Support `DATETIME_INPUT_FORMATS` for `DateTimeField` validation +* Support `TIME_INPUT_FORMATS` for `TimeField` validation ### 2.2.1 -- cgit v1.2.3 From a9d36d4726fc8eea02184b089ee6ed1d02e4c75e Mon Sep 17 00:00:00 2001 From: Stephan Groß Date: Fri, 1 Mar 2013 15:03:27 +0100 Subject: Add docs update - part 1 --- docs/api-guide/fields.md | 24 ++++++++++++++++++------ docs/api-guide/settings.md | 35 +++++++++++++++++++++++++++++++++++ docs/topics/release-notes.md | 4 +--- 3 files changed, 54 insertions(+), 9 deletions(-) (limited to 'docs') diff --git a/docs/api-guide/fields.md b/docs/api-guide/fields.md index abacc1b8..c1f3c051 100644 --- a/docs/api-guide/fields.md +++ b/docs/api-guide/fields.md @@ -185,18 +185,20 @@ Corresponds to `django.forms.fields.RegexField` A date representation. -Uses `DATE_INPUT_FORMATS` to validate date. - Optionally takes `format` as parameter to replace the matching pattern. Corresponds to `django.db.models.fields.DateField` +**Signature:** `DateField(input_formats=None, output_format=False)` + + - `input_formats` designates which input formats are supported. This will override the `DATE_INPUT_FORMATS` + + - `output_format` designates which output format will be used. This will override the `DATE_OUTPUT_FORMAT` + ## DateTimeField A date and time representation. -Uses `DATETIME_INPUT_FORMATS` to validate date_time. - Optionally takes `format` as parameter to replace the matching pattern. Corresponds to `django.db.models.fields.DateTimeField` @@ -211,16 +213,26 @@ If you want to override this behavior, you'll need to declare the `DateTimeField class Meta: model = Comment +**Signature:** `DateTimeField(input_formats=None, output_format=False)` + + - `input_formats` designates which input formats are supported. This will override the `DATETIME_INPUT_FORMATS` + + - `output_format` designates which output format will be used. This will override the `DATETIME_OUTPUT_FORMAT` + ## TimeField A time representation. -Uses `TIME_INPUT_FORMATS` to validate time. - Optionally takes `format` as parameter to replace the matching pattern. Corresponds to `django.db.models.fields.TimeField` +**Signature:** `TimeField(input_formats=None, output_format=False)` + + - `input_formats` designates which input formats are supported. This will override the `TIME_INPUT_FORMATS` + + - `output_format` designates which output format will be used. This will override the `TIME_OUTPUT_FORMAT` + ## IntegerField An integer representation. diff --git a/docs/api-guide/settings.md b/docs/api-guide/settings.md index e103fbab..9080cacb 100644 --- a/docs/api-guide/settings.md +++ b/docs/api-guide/settings.md @@ -174,4 +174,39 @@ The name of a parameter in the URL conf that may be used to provide a format suf Default: `'format'` +## DATE_INPUT_FORMATS + +Default: + + ( + '%Y-%m-%d', # '1984-07-31' + ) + +## DATE_OUTPUT_FORMAT + +## DATETIME_INPUT_FORMATS + +Default: + + ( + '%Y-%m-%d', # '1984-07-31' + '%Y-%m-%d %H:%M', # '1984-07-31 04:31' + '%Y-%m-%d %H:%M:%S', # '1984-07-31 04:31:59' + '%Y-%m-%d %H:%M:%S.%f', # '1984-07-31 04:31:59.000200' + ) + +## DATETIME_OUTPUT_FORMAT + +## TIME_INPUT_FORMATS + +Default: + + ( + '%H:%M', # '04:31' + '%H:%M:%S', # '04:31:59' + '%H:%M:%S.%f', # '04:31:59.000200' + ) + +## TIME_OUTPUT_FORMAT + [cite]: http://www.python.org/dev/peps/pep-0020/ diff --git a/docs/topics/release-notes.md b/docs/topics/release-notes.md index f60382ac..6b9e4e21 100644 --- a/docs/topics/release-notes.md +++ b/docs/topics/release-notes.md @@ -45,9 +45,7 @@ You can determine your currently installed version using `pip freeze`: * Request authentication is no longer lazily evaluated, instead authentication is always run, which results in more consistent, obvious behavior. Eg. Supplying bad auth credentials will now always return an error response, even if no permissions are set on the view. * Bugfix for serializer data being uncacheable with pickle protocol 0. * Bugfixes for model field validation edge-cases. -* Support `DATE_INPUT_FORMATS` for `DateField` validation -* Support `DATETIME_INPUT_FORMATS` for `DateTimeField` validation -* Support `TIME_INPUT_FORMATS` for `TimeField` validation +* Support for custom input and output formats for `DateField`, `DateTimeField` and `TimeField` ### 2.2.1 -- cgit v1.2.3 From 4a2788a7be6541811977fbe7ae31af41bf9545a4 Mon Sep 17 00:00:00 2001 From: Stephan Groß Date: Fri, 1 Mar 2013 16:35:27 +0100 Subject: Update docs --- docs/api-guide/settings.md | 29 +++++++++-------------------- 1 file changed, 9 insertions(+), 20 deletions(-) (limited to 'docs') diff --git a/docs/api-guide/settings.md b/docs/api-guide/settings.md index 9080cacb..04569f44 100644 --- a/docs/api-guide/settings.md +++ b/docs/api-guide/settings.md @@ -176,37 +176,26 @@ Default: `'format'` ## DATE_INPUT_FORMATS -Default: - - ( - '%Y-%m-%d', # '1984-07-31' - ) +Default: `ISO8601` ## DATE_OUTPUT_FORMAT +Default: `ISO8601` + ## DATETIME_INPUT_FORMATS -Default: - - ( - '%Y-%m-%d', # '1984-07-31' - '%Y-%m-%d %H:%M', # '1984-07-31 04:31' - '%Y-%m-%d %H:%M:%S', # '1984-07-31 04:31:59' - '%Y-%m-%d %H:%M:%S.%f', # '1984-07-31 04:31:59.000200' - ) +Default: `ISO8601` ## DATETIME_OUTPUT_FORMAT +Default: `ISO8601` + ## TIME_INPUT_FORMATS -Default: - - ( - '%H:%M', # '04:31' - '%H:%M:%S', # '04:31:59' - '%H:%M:%S.%f', # '04:31:59.000200' - ) +Default: `ISO8601` ## TIME_OUTPUT_FORMAT +Default: `ISO8601` + [cite]: http://www.python.org/dev/peps/pep-0020/ -- cgit v1.2.3 From 4cdb6b2959f6d13417c48781d53c4e7e685934e7 Mon Sep 17 00:00:00 2001 From: Stephan Groß Date: Mon, 4 Mar 2013 13:53:39 +0100 Subject: Fix authtoken migration --- docs/api-guide/settings.md | 12 ++++++++++++ docs/topics/release-notes.md | 1 + 2 files changed, 13 insertions(+) (limited to 'docs') diff --git a/docs/api-guide/settings.md b/docs/api-guide/settings.md index e103fbab..0ecb1d2d 100644 --- a/docs/api-guide/settings.md +++ b/docs/api-guide/settings.md @@ -174,4 +174,16 @@ The name of a parameter in the URL conf that may be used to provide a format suf Default: `'format'` +## REQUIRED_MIGRATIONS + +This is a list of required migrations which are needed by the authtoken migration. + +E.g. + + ( + ('users', '0001_initial'), + ) + +Default: `'()'` + [cite]: http://www.python.org/dev/peps/pep-0020/ diff --git a/docs/topics/release-notes.md b/docs/topics/release-notes.md index 43499c9a..f6ef2c18 100644 --- a/docs/topics/release-notes.md +++ b/docs/topics/release-notes.md @@ -45,6 +45,7 @@ You can determine your currently installed version using `pip freeze`: * Request authentication is no longer lazily evaluated, instead authentication is always run, which results in more consistent, obvious behavior. Eg. Supplying bad auth credentials will now always return an error response, even if no permissions are set on the view. * Bugfix for serializer data being uncacheable with pickle protocol 0. * Bugfixes for model field validation edge-cases. +* Bugfix for authtoken migration while using a custom user model. ### 2.2.1 -- cgit v1.2.3 From d6391359f5cf4be394cf5785edab882f28cb225a Mon Sep 17 00:00:00 2001 From: Stephan Groß Date: Mon, 4 Mar 2013 14:04:03 +0100 Subject: Fix fix migrate authtoken --- docs/api-guide/settings.md | 12 ------------ 1 file changed, 12 deletions(-) (limited to 'docs') diff --git a/docs/api-guide/settings.md b/docs/api-guide/settings.md index 0ecb1d2d..e103fbab 100644 --- a/docs/api-guide/settings.md +++ b/docs/api-guide/settings.md @@ -174,16 +174,4 @@ The name of a parameter in the URL conf that may be used to provide a format suf Default: `'format'` -## REQUIRED_MIGRATIONS - -This is a list of required migrations which are needed by the authtoken migration. - -E.g. - - ( - ('users', '0001_initial'), - ) - -Default: `'()'` - [cite]: http://www.python.org/dev/peps/pep-0020/ -- cgit v1.2.3 From b4c9b68c965c8e07712bf6d173abe4d1e59f8728 Mon Sep 17 00:00:00 2001 From: Stephan Groß Date: Mon, 4 Mar 2013 14:09:59 +0100 Subject: Add note for using authtoken with custom django user model and south --- docs/api-guide/authentication.md | 2 ++ 1 file changed, 2 insertions(+) (limited to 'docs') diff --git a/docs/api-guide/authentication.md b/docs/api-guide/authentication.md index fae86386..80d29ff4 100644 --- a/docs/api-guide/authentication.md +++ b/docs/api-guide/authentication.md @@ -169,6 +169,8 @@ The `obtain_auth_token` view will return a JSON response when valid `username` a Note that the default `obtain_auth_token` view explicitly uses JSON requests and responses, rather than using default renderer and parser classes in your settings. If you need a customized version of the `obtain_auth_token` view, you can do so by overriding the `ObtainAuthToken` view class, and using that in your url conf instead. +**Note:** If you are using `rest_framework.authtoken` with a custom Django user model and South. you have to insert a `needed_by = (('authtoken', '0001_initial'),)` to your user migration. + ## SessionAuthentication This authentication scheme uses Django's default session backend for authentication. Session authentication is appropriate for AJAX clients that are running in the same session context as your website. -- cgit v1.2.3 From 7db2332c4006cd2c79b0ad002bcd9e15f7075ca6 Mon Sep 17 00:00:00 2001 From: Stephan Groß Date: Mon, 4 Mar 2013 14:11:05 +0100 Subject: Update release docs --- docs/topics/release-notes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/topics/release-notes.md b/docs/topics/release-notes.md index f6ef2c18..352b1630 100644 --- a/docs/topics/release-notes.md +++ b/docs/topics/release-notes.md @@ -45,7 +45,7 @@ You can determine your currently installed version using `pip freeze`: * Request authentication is no longer lazily evaluated, instead authentication is always run, which results in more consistent, obvious behavior. Eg. Supplying bad auth credentials will now always return an error response, even if no permissions are set on the view. * Bugfix for serializer data being uncacheable with pickle protocol 0. * Bugfixes for model field validation edge-cases. -* Bugfix for authtoken migration while using a custom user model. +* Bugfix for authtoken migration while using a custom user model and south. ### 2.2.1 -- cgit v1.2.3 From 6c2dbf12208287c6ff81a312db4c4bf7817ca632 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Tue, 5 Mar 2013 14:02:58 +0000 Subject: Minor docs tweak --- docs/api-guide/authentication.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/api-guide/authentication.md b/docs/api-guide/authentication.md index 80d29ff4..38cf6a7d 100644 --- a/docs/api-guide/authentication.md +++ b/docs/api-guide/authentication.md @@ -113,7 +113,12 @@ Unauthenticated responses that are denied permission will result in an `HTTP 401 This authentication scheme 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` scheme, include `rest_framework.authtoken` in your `INSTALLED_APPS` setting. +To use the `TokenAuthentication` scheme, include `rest_framework.authtoken` in your `INSTALLED_APPS` setting: + + INSTALLED_APPS = ( + ... + 'rest_framework.authtoken' + ) You'll also need to create tokens for your users. -- cgit v1.2.3 From 6e7ddd579b6604d1b0d6da8e4d09762be4520e35 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Tue, 5 Mar 2013 17:39:34 +0000 Subject: Docs tweak. --- docs/api-guide/authentication.md | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) (limited to 'docs') diff --git a/docs/api-guide/authentication.md b/docs/api-guide/authentication.md index 38cf6a7d..9d6b4c60 100644 --- a/docs/api-guide/authentication.md +++ b/docs/api-guide/authentication.md @@ -140,10 +140,14 @@ Unauthenticated responses that are denied permission will result in an `HTTP 401 WWW-Authenticate: Token +--- + **Note:** If you use `TokenAuthentication` in production you must ensure that your API is only available over `https` only. --- +#### Generating Tokens + If you want every user to have an automatically generated Token, you can simply catch the User's `post_save` signal. @receiver(post_save, sender=User) @@ -159,8 +163,7 @@ If you've already created some users, you can generate tokens for all existing u for user in User.objects.all(): Token.objects.get_or_create(user=user) -When using `TokenAuthentication`, you may want to provide a mechanism for clients to obtain a token given the username and password. -REST framework provides a built-in view to provide this behavior. To use it, add the `obtain_auth_token` view to your URLconf: +When using `TokenAuthentication`, you may want to provide a mechanism for clients to obtain a token given the username and password. REST framework provides a built-in view to provide this behavior. To use it, add the `obtain_auth_token` view to your URLconf: urlpatterns += patterns('', url(r'^api-token-auth/', 'rest_framework.authtoken.views.obtain_auth_token') @@ -174,7 +177,22 @@ The `obtain_auth_token` view will return a JSON response when valid `username` a Note that the default `obtain_auth_token` view explicitly uses JSON requests and responses, rather than using default renderer and parser classes in your settings. If you need a customized version of the `obtain_auth_token` view, you can do so by overriding the `ObtainAuthToken` view class, and using that in your url conf instead. -**Note:** If you are using `rest_framework.authtoken` with a custom Django user model and South. you have to insert a `needed_by = (('authtoken', '0001_initial'),)` to your user migration. +#### Custom user models + +The `rest_framework.authtoken` app includes a south migration that will create the authtoken table. If you're using a [custom user model][custom-user-model] you'll need to make sure that any initial migration that creates the user table runs before the authtoken table is created. + +You can do so by inserting a `needed_by` attribute in your user migration: + + class Migration: + + needed_by = ( + ('authtoken', '0001_initial'), + ) + + def forwards(self): + ... + +For more details, see the [south documentation on dependancies][south-dependancies]. ## SessionAuthentication @@ -240,5 +258,7 @@ HTTP digest authentication is a widely implemented scheme that was intended to r [throttling]: throttling.md [csrf-ajax]: https://docs.djangoproject.com/en/dev/ref/contrib/csrf/#ajax [mod_wsgi_official]: http://code.google.com/p/modwsgi/wiki/ConfigurationDirectives#WSGIPassAuthorization +[custom-user-model]: https://docs.djangoproject.com/en/dev/topics/auth/customizing/#specifying-a-custom-user-model +[south-dependancies]: http://south.readthedocs.org/en/latest/dependencies.html [juanriaza]: https://github.com/juanriaza [djangorestframework-digestauth]: https://github.com/juanriaza/django-rest-framework-digestauth -- cgit v1.2.3 From 7464def4e380d790672c83f21f7da1aa229a95e8 Mon Sep 17 00:00:00 2001 From: Stephan Groß Date: Tue, 5 Mar 2013 18:42:31 +0100 Subject: Fix typo --- docs/api-guide/authentication.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'docs') diff --git a/docs/api-guide/authentication.md b/docs/api-guide/authentication.md index 9d6b4c60..ce2c99e1 100644 --- a/docs/api-guide/authentication.md +++ b/docs/api-guide/authentication.md @@ -192,7 +192,7 @@ You can do so by inserting a `needed_by` attribute in your user migration: def forwards(self): ... -For more details, see the [south documentation on dependancies][south-dependancies]. +For more details, see the [south documentation on dependencies][south-dependencies]. ## SessionAuthentication @@ -259,6 +259,6 @@ HTTP digest authentication is a widely implemented scheme that was intended to r [csrf-ajax]: https://docs.djangoproject.com/en/dev/ref/contrib/csrf/#ajax [mod_wsgi_official]: http://code.google.com/p/modwsgi/wiki/ConfigurationDirectives#WSGIPassAuthorization [custom-user-model]: https://docs.djangoproject.com/en/dev/topics/auth/customizing/#specifying-a-custom-user-model -[south-dependancies]: http://south.readthedocs.org/en/latest/dependencies.html +[south-dependencies]: http://south.readthedocs.org/en/latest/dependencies.html [juanriaza]: https://github.com/juanriaza [djangorestframework-digestauth]: https://github.com/juanriaza/django-rest-framework-digestauth -- cgit v1.2.3 From 17e0ff0fcde23f4bc6734b75f7fff734ae77c26d Mon Sep 17 00:00:00 2001 From: Stephan Groß Date: Tue, 5 Mar 2013 18:45:09 +0100 Subject: Add @iekadou for #700 support. 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 d1bb907a..190ce490 100644 --- a/docs/topics/credits.md +++ b/docs/topics/credits.md @@ -107,6 +107,7 @@ The following people have helped make REST framework great. * Ryan Detzel - [ryanrdetzel] * Omer Katz - [thedrow] * Wiliam Souza - [waa] +* Jonas Braun - [iekadou] Many thanks to everyone who's contributed to the project. @@ -248,3 +249,4 @@ You can also contact [@_tomchristie][twitter] directly on twitter. [ryanrdetzel]: https://github.com/ryanrdetzel [thedrow]: https://github.com/thedrow [waa]: https://github.com/wiliamsouza +[iekadou]: https://github.com/iekadou -- cgit v1.2.3 From 4f7b028a0a983b79ebca63b2ba48ce97e7a06175 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Tue, 5 Mar 2013 20:57:35 +0000 Subject: Updating docs --- docs/api-guide/fields.md | 45 +++++++++++++++++++++++---------------------- docs/api-guide/settings.md | 36 ++++++++++++++++++++++++------------ 2 files changed, 47 insertions(+), 34 deletions(-) (limited to 'docs') diff --git a/docs/api-guide/fields.md b/docs/api-guide/fields.md index c1f3c051..68e619a0 100644 --- a/docs/api-guide/fields.md +++ b/docs/api-guide/fields.md @@ -181,26 +181,10 @@ Corresponds to `django.forms.fields.RegexField` **Signature:** `RegexField(regex, max_length=None, min_length=None)` -## DateField - -A date representation. - -Optionally takes `format` as parameter to replace the matching pattern. - -Corresponds to `django.db.models.fields.DateField` - -**Signature:** `DateField(input_formats=None, output_format=False)` - - - `input_formats` designates which input formats are supported. This will override the `DATE_INPUT_FORMATS` - - - `output_format` designates which output format will be used. This will override the `DATE_OUTPUT_FORMAT` - ## DateTimeField A date and time representation. -Optionally takes `format` as parameter to replace the matching pattern. - Corresponds to `django.db.models.fields.DateTimeField` When using `ModelSerializer` or `HyperlinkedModelSerializer`, note that any model fields with `auto_now=True` or `auto_now_add=True` will use serializer fields that are `read_only=True` by default. @@ -213,11 +197,25 @@ If you want to override this behavior, you'll need to declare the `DateTimeField class Meta: model = Comment -**Signature:** `DateTimeField(input_formats=None, output_format=False)` +**Signature:** `DateTimeField(format=None, input_formats=None)` + +* `format` - A string representing the output format. If not specified, the `DATETIME_FORMAT` setting will be used, which defaults to `'iso8601'`. +* `input_formats` - A list of strings representing the input formats which may be used to parse the date. If not specified, the `DATETIME_INPUT_FORMATS` setting will be used, which defaults to `['iso8601']`. + +DateTime format strings may either be [python strftime formats][strftime] which explicitly specifiy the format, or the special string `'is8601'`, which indicates that [ISO 8601][iso8601] style datetimes should be used. (eg `'2013-01-29T12:34:56.000000'`) + +## DateField + +A date representation. + +Corresponds to `django.db.models.fields.DateField` + +**Signature:** `DateField(format=None, input_formats=None)` - - `input_formats` designates which input formats are supported. This will override the `DATETIME_INPUT_FORMATS` +* `format` - A string representing the output format. If not specified, the `DATE_FORMAT` setting will be used, which defaults to `'iso8601'`. +* `input_formats` - A list of strings representing the input formats which may be used to parse the date. If not specified, the `DATE_INPUT_FORMATS` setting will be used, which defaults to `['iso8601']`. - - `output_format` designates which output format will be used. This will override the `DATETIME_OUTPUT_FORMAT` +Date format strings may either be [python strftime formats][strftime] which explicitly specifiy the format, or the special string `'is8601'`, which indicates that [ISO 8601][iso8601] style dates should be used. (eg `'2013-01-29'`) ## TimeField @@ -227,11 +225,12 @@ Optionally takes `format` as parameter to replace the matching pattern. Corresponds to `django.db.models.fields.TimeField` -**Signature:** `TimeField(input_formats=None, output_format=False)` +**Signature:** `TimeField(format=None, input_formats=None)` - - `input_formats` designates which input formats are supported. This will override the `TIME_INPUT_FORMATS` +* `format` - A string representing the output format. If not specified, the `TIME_FORMAT` setting will be used, which defaults to `'iso8601'`. +* `input_formats` - A list of strings representing the input formats which may be used to parse the date. If not specified, the `TIME_INPUT_FORMATS` setting will be used, which defaults to `['iso8601']`. - - `output_format` designates which output format will be used. This will override the `TIME_OUTPUT_FORMAT` +Time format strings may either be [python strftime formats][strftime] which explicitly specifiy the format, or the special string `'is8601'`, which indicates that [ISO 8601][iso8601] style times should be used. (eg `'12:34:56.000000'`) ## IntegerField @@ -276,3 +275,5 @@ Django's regular [FILE_UPLOAD_HANDLERS] are used for handling uploaded files. [cite]: https://docs.djangoproject.com/en/dev/ref/forms/api/#django.forms.Form.cleaned_data [FILE_UPLOAD_HANDLERS]: https://docs.djangoproject.com/en/dev/ref/settings/#std:setting-FILE_UPLOAD_HANDLERS +[strftime]: http://docs.python.org/2/library/datetime.html#strftime-and-strptime-behavior +[iso8601]: http://www.w3.org/TR/NOTE-datetime diff --git a/docs/api-guide/settings.md b/docs/api-guide/settings.md index 04569f44..82730225 100644 --- a/docs/api-guide/settings.md +++ b/docs/api-guide/settings.md @@ -174,28 +174,40 @@ The name of a parameter in the URL conf that may be used to provide a format suf Default: `'format'` -## DATE_INPUT_FORMATS - -Default: `ISO8601` +## DATETIME_FORMAT -## DATE_OUTPUT_FORMAT +A format string that should be used by default for `DateTimeField` serializer fields. -Default: `ISO8601` +Default: `'iso8601'` ## DATETIME_INPUT_FORMATS -Default: `ISO8601` +A list of format strings that should be used by default for parsing inputs to `DateTimeField` serializer fields. -## DATETIME_OUTPUT_FORMAT +Default: `['iso8601']` -Default: `ISO8601` +## DATE_FORMAT -## TIME_INPUT_FORMATS +A format string that should be used by default for `DateField` serializer fields. + +Default: `'iso8601'` + +## DATE_INPUT_FORMATS -Default: `ISO8601` +A list of format strings that should be used by default for parsing inputs to `DateField` serializer fields. + +Default: `['iso8601']` + +## TIME_FORMAT + +A format string that should be used by default for `TimeField` serializer fields. + +Default: `'iso8601'` + +## TIME_INPUT_FORMATS -## TIME_OUTPUT_FORMAT +A list of format strings that should be used by default for parsing inputs to `TimeField` serializer fields. -Default: `ISO8601` +Default: `['iso8601']` [cite]: http://www.python.org/dev/peps/pep-0020/ -- cgit v1.2.3 From 1106596c80218569a56ff5ea04d759e3d0c541dd Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Wed, 6 Mar 2013 12:19:39 +0000 Subject: Clean ups to datetime formatting --- docs/api-guide/fields.md | 20 ++++----- docs/api-guide/settings.md | 104 ++++++++++++++++++++++++++++--------------- docs/topics/release-notes.md | 2 +- 3 files changed, 79 insertions(+), 47 deletions(-) (limited to 'docs') diff --git a/docs/api-guide/fields.md b/docs/api-guide/fields.md index 68e619a0..9a745cf1 100644 --- a/docs/api-guide/fields.md +++ b/docs/api-guide/fields.md @@ -2,7 +2,7 @@ # Serializer fields -> Each field in a Form class is responsible not only for validating data, but also for "cleaning" it -- normalizing it to a consistent format. +> Each field in a Form class is responsible not only for validating data, but also for "cleaning" it — normalizing it to a consistent format. > > — [Django documentation][cite] @@ -199,10 +199,10 @@ If you want to override this behavior, you'll need to declare the `DateTimeField **Signature:** `DateTimeField(format=None, input_formats=None)` -* `format` - A string representing the output format. If not specified, the `DATETIME_FORMAT` setting will be used, which defaults to `'iso8601'`. -* `input_formats` - A list of strings representing the input formats which may be used to parse the date. If not specified, the `DATETIME_INPUT_FORMATS` setting will be used, which defaults to `['iso8601']`. +* `format` - A string representing the output format. If not specified, the `DATETIME_FORMAT` setting will be used, which defaults to `'iso-8601'`. +* `input_formats` - A list of strings representing the input formats which may be used to parse the date. If not specified, the `DATETIME_INPUT_FORMATS` setting will be used, which defaults to `['iso-8601']`. -DateTime format strings may either be [python strftime formats][strftime] which explicitly specifiy the format, or the special string `'is8601'`, which indicates that [ISO 8601][iso8601] style datetimes should be used. (eg `'2013-01-29T12:34:56.000000'`) +DateTime format strings may either be [python strftime formats][strftime] which explicitly specifiy the format, or the special string `'iso-8601'`, which indicates that [ISO 8601][iso8601] style datetimes should be used. (eg `'2013-01-29T12:34:56.000000'`) ## DateField @@ -212,10 +212,10 @@ Corresponds to `django.db.models.fields.DateField` **Signature:** `DateField(format=None, input_formats=None)` -* `format` - A string representing the output format. If not specified, the `DATE_FORMAT` setting will be used, which defaults to `'iso8601'`. -* `input_formats` - A list of strings representing the input formats which may be used to parse the date. If not specified, the `DATE_INPUT_FORMATS` setting will be used, which defaults to `['iso8601']`. +* `format` - A string representing the output format. If not specified, the `DATE_FORMAT` setting will be used, which defaults to `'iso-8601'`. +* `input_formats` - A list of strings representing the input formats which may be used to parse the date. If not specified, the `DATE_INPUT_FORMATS` setting will be used, which defaults to `['iso-8601']`. -Date format strings may either be [python strftime formats][strftime] which explicitly specifiy the format, or the special string `'is8601'`, which indicates that [ISO 8601][iso8601] style dates should be used. (eg `'2013-01-29'`) +Date format strings may either be [python strftime formats][strftime] which explicitly specifiy the format, or the special string `'iso-8601'`, which indicates that [ISO 8601][iso8601] style dates should be used. (eg `'2013-01-29'`) ## TimeField @@ -227,10 +227,10 @@ Corresponds to `django.db.models.fields.TimeField` **Signature:** `TimeField(format=None, input_formats=None)` -* `format` - A string representing the output format. If not specified, the `TIME_FORMAT` setting will be used, which defaults to `'iso8601'`. -* `input_formats` - A list of strings representing the input formats which may be used to parse the date. If not specified, the `TIME_INPUT_FORMATS` setting will be used, which defaults to `['iso8601']`. +* `format` - A string representing the output format. If not specified, the `TIME_FORMAT` setting will be used, which defaults to `'iso-8601'`. +* `input_formats` - A list of strings representing the input formats which may be used to parse the date. If not specified, the `TIME_INPUT_FORMATS` setting will be used, which defaults to `['iso-8601']`. -Time format strings may either be [python strftime formats][strftime] which explicitly specifiy the format, or the special string `'is8601'`, which indicates that [ISO 8601][iso8601] style times should be used. (eg `'12:34:56.000000'`) +Time format strings may either be [python strftime formats][strftime] which explicitly specifiy the format, or the special string `'iso-8601'`, which indicates that [ISO 8601][iso8601] style times should be used. (eg `'12:34:56.000000'`) ## IntegerField diff --git a/docs/api-guide/settings.md b/docs/api-guide/settings.md index 82730225..11638696 100644 --- a/docs/api-guide/settings.md +++ b/docs/api-guide/settings.md @@ -34,7 +34,11 @@ The `api_settings` object will check for any user-defined settings, and otherwis # API Reference -## DEFAULT_RENDERER_CLASSES +## API policy settings + +*The following settings control the basic API policies, and are applied to every `APIView` class based view, or `@api_view` function based view.* + +#### DEFAULT_RENDERER_CLASSES A list or tuple of renderer classes, that determines the default set of renderers that may be used when returning a `Response` object. @@ -45,7 +49,7 @@ Default: 'rest_framework.renderers.BrowsableAPIRenderer', ) -## DEFAULT_PARSER_CLASSES +#### DEFAULT_PARSER_CLASSES A list or tuple of parser classes, that determines the default set of parsers used when accessing the `request.DATA` property. @@ -57,7 +61,7 @@ Default: 'rest_framework.parsers.MultiPartParser' ) -## DEFAULT_AUTHENTICATION_CLASSES +#### DEFAULT_AUTHENTICATION_CLASSES A list or tuple of authentication classes, that determines the default set of authenticators used when accessing the `request.user` or `request.auth` properties. @@ -68,7 +72,7 @@ Default: 'rest_framework.authentication.BasicAuthentication' ) -## DEFAULT_PERMISSION_CLASSES +#### DEFAULT_PERMISSION_CLASSES A list or tuple of permission classes, that determines the default set of permissions checked at the start of a view. @@ -78,59 +82,77 @@ Default: 'rest_framework.permissions.AllowAny', ) -## DEFAULT_THROTTLE_CLASSES +#### DEFAULT_THROTTLE_CLASSES A list or tuple of throttle classes, that determines the default set of throttles checked at the start of a view. Default: `()` -## DEFAULT_CONTENT_NEGOTIATION_CLASS +#### DEFAULT_CONTENT_NEGOTIATION_CLASS A content negotiation class, that determines how a renderer is selected for the response, given an incoming request. Default: `'rest_framework.negotiation.DefaultContentNegotiation'` -## DEFAULT_MODEL_SERIALIZER_CLASS +--- + +## Generic view settings + +*The following settings control the behavior of the generic class based views.* + +#### DEFAULT_MODEL_SERIALIZER_CLASS A class that determines the default type of model serializer that should be used by a generic view if `model` is specified, but `serializer_class` is not provided. Default: `'rest_framework.serializers.ModelSerializer'` -## DEFAULT_PAGINATION_SERIALIZER_CLASS +#### DEFAULT_PAGINATION_SERIALIZER_CLASS A class the determines the default serialization style for paginated responses. Default: `rest_framework.pagination.PaginationSerializer` -## FILTER_BACKEND +#### FILTER_BACKEND The filter backend class that should be used for generic filtering. If set to `None` then generic filtering is disabled. -## PAGINATE_BY +#### PAGINATE_BY The default page size to use for pagination. If set to `None`, pagination is disabled by default. Default: `None` -## PAGINATE_BY_PARAM +#### PAGINATE_BY_PARAM The name of a query parameter, which can be used by the client to overide the default page size to use for pagination. If set to `None`, clients may not override the default page size. Default: `None` -## UNAUTHENTICATED_USER +--- + +## Authentication settings + +*The following settings control the behavior of unauthenticated requests.* + +#### UNAUTHENTICATED_USER The class that should be used to initialize `request.user` for unauthenticated requests. Default: `django.contrib.auth.models.AnonymousUser` -## UNAUTHENTICATED_TOKEN +#### UNAUTHENTICATED_TOKEN The class that should be used to initialize `request.auth` for unauthenticated requests. Default: `None` -## FORM_METHOD_OVERRIDE +--- + +## Browser overrides + +*The following settings provide URL or form-based overrides of the default browser behavior.* + +#### FORM_METHOD_OVERRIDE The name of a form field that may be used to override the HTTP method of the form. @@ -138,7 +160,7 @@ If the value of this setting is `None` then form method overloading will be disa Default: `'_method'` -## FORM_CONTENT_OVERRIDE +#### FORM_CONTENT_OVERRIDE The name of a form field that may be used to override the content of the form payload. Must be used together with `FORM_CONTENTTYPE_OVERRIDE`. @@ -146,7 +168,7 @@ If either setting is `None` then form content overloading will be disabled. Default: `'_content'` -## FORM_CONTENTTYPE_OVERRIDE +#### FORM_CONTENTTYPE_OVERRIDE The name of a form field that may be used to override the content type of the form payload. Must be used together with `FORM_CONTENT_OVERRIDE`. @@ -154,7 +176,7 @@ If either setting is `None` then form content overloading will be disabled. Default: `'_content_type'` -## URL_ACCEPT_OVERRIDE +#### URL_ACCEPT_OVERRIDE The name of a URL parameter that may be used to override the HTTP `Accept` header. @@ -162,52 +184,62 @@ If the value of this setting is `None` then URL accept overloading will be disab Default: `'accept'` -## URL_FORMAT_OVERRIDE +#### URL_FORMAT_OVERRIDE The name of a URL parameter that may be used to override the default `Accept` header based content negotiation. Default: `'format'` -## FORMAT_SUFFIX_KWARG +--- -The name of a parameter in the URL conf that may be used to provide a format suffix. +## Date/Time formatting -Default: `'format'` +*The following settings are used to control how date and time representations may be parsed and rendered.* -## DATETIME_FORMAT +#### DATETIME_FORMAT -A format string that should be used by default for `DateTimeField` serializer fields. +A format string that should be used by default for rendering the output of `DateTimeField` serializer fields. -Default: `'iso8601'` +Default: `'iso-8601'` -## DATETIME_INPUT_FORMATS +#### DATETIME_INPUT_FORMATS A list of format strings that should be used by default for parsing inputs to `DateTimeField` serializer fields. -Default: `['iso8601']` +Default: `['iso-8601']` -## DATE_FORMAT +#### DATE_FORMAT -A format string that should be used by default for `DateField` serializer fields. +A format string that should be used by default for rendering the output of `DateField` serializer fields. -Default: `'iso8601'` +Default: `'iso-8601'` -## DATE_INPUT_FORMATS +#### DATE_INPUT_FORMATS A list of format strings that should be used by default for parsing inputs to `DateField` serializer fields. -Default: `['iso8601']` +Default: `['iso-8601']` -## TIME_FORMAT +#### TIME_FORMAT -A format string that should be used by default for `TimeField` serializer fields. +A format string that should be used by default for rendering the output of `TimeField` serializer fields. -Default: `'iso8601'` +Default: `'iso-8601'` -## TIME_INPUT_FORMATS +#### TIME_INPUT_FORMATS A list of format strings that should be used by default for parsing inputs to `TimeField` serializer fields. -Default: `['iso8601']` +Default: `['iso-8601']` + +--- + +## Miscellaneous settings + +#### FORMAT_SUFFIX_KWARG + +The name of a parameter in the URL conf that may be used to provide a format suffix. + +Default: `'format'` [cite]: http://www.python.org/dev/peps/pep-0020/ diff --git a/docs/topics/release-notes.md b/docs/topics/release-notes.md index 81ed0c84..df66cb35 100644 --- a/docs/topics/release-notes.md +++ b/docs/topics/release-notes.md @@ -42,7 +42,7 @@ You can determine your currently installed version using `pip freeze`: ### Master -* Support for custom input and output formats for `DateField`, `DateTimeField` and `TimeField` +* Support for custom input and output formats for `DateField`, `DateTimeField` and `TimeField`. * Cleanup: Request authentication is no longer lazily evaluated, instead authentication is always run, which results in more consistent, obvious behavior. Eg. Supplying bad auth credentials will now always return an error response, even if no permissions are set on the view. * Bugfix for serializer data being uncacheable with pickle protocol 0. * Bugfixes for model field validation edge-cases. -- cgit v1.2.3 From d260f1ec15d5aa3085fa74118382bcf2fd752dca Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Wed, 6 Mar 2013 12:19:49 +0000 Subject: Add `tox` note. --- docs/index.md | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'docs') diff --git a/docs/index.md b/docs/index.md index b2c04735..faad6afe 100644 --- a/docs/index.md +++ b/docs/index.md @@ -133,6 +133,10 @@ Run the tests: ./rest_framework/runtests/runtests.py +To run the tests against all supported configurations, first install [the tox testing tool][tox] globally, using `pip install tox`, then simply run `tox`: + + tox + ## Support For support please see the [REST framework discussion group][group], try the `#restframework` channel on `irc.freenode.net`, or raise a question on [Stack Overflow][stack-overflow], making sure to include the ['django-rest-framework'][django-rest-framework-tag] tag. @@ -218,6 +222,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. [release-notes]: topics/release-notes.md [credits]: topics/credits.md +[tox]: http://testrun.org/tox/latest/ + [group]: https://groups.google.com/forum/?fromgroups#!forum/django-rest-framework [stack-overflow]: http://stackoverflow.com/ [django-rest-framework-tag]: http://stackoverflow.com/questions/tagged/django-rest-framework -- cgit v1.2.3 From cdf7c778d828eaadfe14a39495f854903b10843a Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Wed, 6 Mar 2013 12:29:56 +0000 Subject: Version 2.2.2 --- docs/topics/release-notes.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/topics/release-notes.md b/docs/topics/release-notes.md index df66cb35..42b1d8da 100644 --- a/docs/topics/release-notes.md +++ b/docs/topics/release-notes.md @@ -40,7 +40,9 @@ You can determine your currently installed version using `pip freeze`: ## 2.2.x series -### Master +### 2.2.2 + +**Date**: 6th March 2013 * Support for custom input and output formats for `DateField`, `DateTimeField` and `TimeField`. * Cleanup: Request authentication is no longer lazily evaluated, instead authentication is always run, which results in more consistent, obvious behavior. Eg. Supplying bad auth credentials will now always return an error response, even if no permissions are set on the view. -- cgit v1.2.3 From ddd7125a63c5187483058bad27c94676b9b6c16e Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Wed, 6 Mar 2013 13:35:04 +0000 Subject: Tweak travis badge positioning. --- docs/css/default.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/css/default.css b/docs/css/default.css index 07c4884d..c160b63d 100644 --- a/docs/css/default.css +++ b/docs/css/default.css @@ -47,7 +47,7 @@ body.index-page #main-content iframe.twitter-share-button { body.index-page #main-content img.travis-build-image { float: right; margin-right: 8px; - margin-top: -9px; + margin-top: -11px; margin-bottom: 0px; } -- cgit v1.2.3 From 30e3775b8b209242141357bad0a69b6cc503c6f9 Mon Sep 17 00:00:00 2001 From: Pierre Dulac Date: Sat, 2 Mar 2013 20:36:53 +0100 Subject: Update the documentation with a warning for incompatibility with Python 3 and taking @tomchristie advice into account on how to reformulate some sentences --- docs/api-guide/authentication.md | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) (limited to 'docs') diff --git a/docs/api-guide/authentication.md b/docs/api-guide/authentication.md index c73de1f6..b7251fd0 100644 --- a/docs/api-guide/authentication.md +++ b/docs/api-guide/authentication.md @@ -184,7 +184,13 @@ If you're using an AJAX style API with SessionAuthentication, you'll need to mak ## OAuth2Authentication -This authentication uses [OAuth 2.0][rfc6749] authentication scheme. It depends on optional [`django-oauth2-provider`][django-oauth2-provider]. In order to make it work you must install this package and add `provider` and `provider.oauth2` to your `INSTALLED_APPS` : +--- + +** Note:** This isn't available for Python 3, because the module [`django-oauth2-provider`][django-oauth2-provider] is not Python 3 ready. + +--- + +This authentication uses [OAuth 2.0][rfc6749] authentication scheme. It depends on the optional [`django-oauth2-provider`][django-oauth2-provider] project. In order to make it work you must install this package and add `provider` and `provider.oauth2` to your `INSTALLED_APPS` : INSTALLED_APPS = ( #(...) @@ -207,7 +213,7 @@ Finally, sync your database with those two new django apps. $ python manage.py syncdb $ python manage.py migrate -`OAuth2Authentication` class provides only token verification for requests. The *oauth 2 dance* is taken care by the [`django-oaut2-provider`][django-oauth2-provider] dependency. Unfortunately, there isn't a lot of [documentation][django-oauth2-provider--doc] currently on how to *dance* with this package on the client side. +`OAuth2Authentication` class provides only token verification for requests. The *oauth 2 dance* is taken care by the [`django-oaut2-provider`][django-oauth2-provider] dependency. The official [documentation][django-oauth2-provider--doc] is being [rewritten][django-oauth2-provider--rewritten-doc]. The Good news is, here is a minimal "How to start" because **OAuth 2** is dramatically simpler than **OAuth 1**, so no more headache with signature, cryptography on client side, and other complex things. @@ -228,13 +234,13 @@ Your client interface – I mean by that your iOS code, HTML code, or whatev --- -**Note:** Remember that you are **highly encourage** to use HTTPS for all your OAuth 2 requests. And by *highly encourage* I mean you SHOULD always use HTTPS otherwise you will expose user passwords for any person who can intercept the request (like a man in the middle attack). +**Note:** Remember that you should use HTTPS in production. --- You can use the command line to test that your local configuration is working : - $ curl -X POST -d "client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET&grant_type=password&username=YOUR_USERNAME&password=YOU_PASSWORD" http://localhost:8000/oauth2/access_token/ + $ curl -X POST -d "client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET&grant_type=password&username=YOUR_USERNAME&password=YOUR_PASSWORD" http://localhost:8000/oauth2/access_token/ Here is the response you should get : @@ -248,7 +254,7 @@ The command line to test the authentication looks like : $ curl -H "Authorization: Bearer " http://localhost:8000/api/?client_id=YOUR_CLIENT_ID\&client_secret=YOUR_CLIENT_SECRET -And hopefully, it will work like a charm. +And it will work like a charm. # Custom authentication @@ -305,4 +311,5 @@ HTTP digest authentication is a widely implemented scheme that was intended to r [djangorestframework-digestauth]: https://github.com/juanriaza/django-rest-framework-digestauth [django-oauth2-provider]: https://github.com/caffeinehit/django-oauth2-provider [django-oauth2-provider--doc]: https://django-oauth2-provider.readthedocs.org/en/latest/ +[django-oauth2-provider--rewritten-doc]: http://django-oauth2-provider-dulaccc.readthedocs.org/en/latest/ [rfc6749]: http://tools.ietf.org/html/rfc6749 -- cgit v1.2.3 From 4e80541824bab0712a816716c5c63ec5623370d8 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Thu, 7 Mar 2013 09:05:13 +0000 Subject: Version 2.2.3 --- docs/topics/release-notes.md | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'docs') diff --git a/docs/topics/release-notes.md b/docs/topics/release-notes.md index 42b1d8da..535da433 100644 --- a/docs/topics/release-notes.md +++ b/docs/topics/release-notes.md @@ -40,6 +40,12 @@ You can determine your currently installed version using `pip freeze`: ## 2.2.x series +### 2.2.3 + +**Date**: 7th March 2013 + +* Bugfix: Fix None values for for `DateField`, `DateTimeField` and `TimeField`. + ### 2.2.2 **Date**: 6th March 2013 -- cgit v1.2.3 From c2eb27629cf13e044fe81f338ac912cabf9f891f Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Thu, 7 Mar 2013 17:50:48 +0000 Subject: Update docs for OAuth 2.0 --- docs/index.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/index.md b/docs/index.md index 7c472e35..8e5097b3 100644 --- a/docs/index.md +++ b/docs/index.md @@ -37,8 +37,9 @@ The following packages are optional: * [defusedxml][defusedxml] (0.3+) - XML content-type support. * [django-filter][django-filter] (0.5.4+) - Filtering support. * [django-oauth-plus][django-oauth-plus] (2.0+) and [oauth2][oauth2] (1.5.211+) - OAuth 1.0a support. +* [django-oauth2-provider][django-oauth2-provider] (0.2.3+) - OAuth 2.0 support. -**Note**: The `oauth2` python package is badly misnamed, and actually provides oauth1.0a support. +**Note**: The `oauth2` python package is badly misnamed, and actually provides OAuth 1.0a support. Also note that packages required for both OAuth 1.0a, and OAuth 2.0 are not yet Python 3 compatible. ## Installation @@ -185,6 +186,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. [django-filter]: http://pypi.python.org/pypi/django-filter [oauth2]: https://github.com/simplegeo/python-oauth2 [django-oauth-plus]: https://bitbucket.org/david/django-oauth-plus/wiki/Home +[django-oauth2-provider]: https://github.com/caffeinehit/django-oauth2-provider [0.4]: https://github.com/tomchristie/django-rest-framework/tree/0.4.X [image]: img/quickstart.png [sandbox]: http://restframework.herokuapp.com/ -- cgit v1.2.3 From e42e49852d032a888a17a09be6732a4c6a8fee72 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Thu, 7 Mar 2013 19:49:36 +0000 Subject: Tweak docs --- docs/api-guide/authentication.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'docs') diff --git a/docs/api-guide/authentication.md b/docs/api-guide/authentication.md index 52d43b5e..9234938c 100644 --- a/docs/api-guide/authentication.md +++ b/docs/api-guide/authentication.md @@ -220,11 +220,11 @@ OAuthAuthentication class provides only token verification and signature validat #### Getting started with django-oauth-plus -The `django-oauth-plus` package provides simple foundation for classic 'three-legged' oauth flow, so if it is what you need please refer to [its documentation](http://code.larlet.fr/django-oauth-plus/wiki/Home). This documentation will provide you also information about how to work with supplied models and change basic settings. +The `django-oauth-plus` package provides simple foundation for classic 'three-legged' oauth flow, so if it is what you need please refer to [its documentation][django-oauth-plus]. This documentation will provide you also information about how to work with supplied models and change basic settings. ## OAuth2Authentication -This authentication uses [OAuth 2.0][rfc6749] authentication scheme. It depends on the optional [`django-oauth2-provider`][django-oauth2-provider] project. In order to make it work you must install this package and add `provider` and `provider.oauth2` to your `INSTALLED_APPS` : +This authentication uses [OAuth 2.0][rfc6749] authentication scheme. It depends on the optional [django-oauth2-provider][django-oauth2-provider] project. In order to make it work you must install this package and add `provider` and `provider.oauth2` to your `INSTALLED_APPS` : INSTALLED_APPS = ( ... @@ -236,14 +236,14 @@ And include the urls needed in your root `urls.py` file to be able to begin the url(r'^oauth2/', include('provider.oauth2.urls', namespace='oauth2')), -** Note**: The `namespace` argument is required +**Note**: The `namespace` argument is required Finally, sync your database with those two new django apps. $ python manage.py syncdb $ python manage.py migrate -`OAuth2Authentication` class provides only token verification for requests. The *oauth 2 dance* is taken care by the [`django-oaut2-provider`][django-oauth2-provider] dependency. The official [documentation][django-oauth2-provider--doc] is being [rewritten][django-oauth2-provider--rewritten-doc]. +`OAuth2Authentication` class provides only token verification for requests. The *oauth 2 dance* is taken care by the [django-oaut2-provider][django-oauth2-provider] dependency. The official [documentation][django-oauth2-provider--doc] is being [rewritten][django-oauth2-provider--rewritten-doc]. The Good news is, here is a minimal "How to start" because **OAuth 2** is dramatically simpler than **OAuth 1**, so no more headache with signature, cryptography on client side, and other complex things. @@ -284,6 +284,8 @@ The command line to test the authentication looks like: $ curl -H "Authorization: Bearer " http://localhost:8000/api/?client_id=YOUR_CLIENT_ID\&client_secret=YOUR_CLIENT_SECRET +--- + # Custom authentication To implement a custom authentication scheme, subclass `BaseAuthentication` and override the `.authenticate(self, request)` method. The method should return a two-tuple of `(user, auth)` if authentication succeeds, or `None` otherwise. @@ -340,6 +342,7 @@ HTTP digest authentication is a widely implemented scheme that was intended to r [juanriaza]: https://github.com/juanriaza [djangorestframework-digestauth]: https://github.com/juanriaza/django-rest-framework-digestauth [oauth-1.0a]: http://oauth.net/core/1.0a +[django-oauth-plus]: http://code.larlet.fr/django-oauth-plus [django-oauth2-provider]: https://github.com/caffeinehit/django-oauth2-provider [django-oauth2-provider--doc]: https://django-oauth2-provider.readthedocs.org/en/latest/ [django-oauth2-provider--rewritten-doc]: http://django-oauth2-provider-dulaccc.readthedocs.org/en/latest/ -- cgit v1.2.3 From 66605acaf02d46eb899f495137afb4f9ff127ff0 Mon Sep 17 00:00:00 2001 From: Ian Dash Date: Thu, 7 Mar 2013 17:29:25 +0000 Subject: Errors during deserializing lists now return a list of tuples with index of bad item in data plus usual errors dict --- docs/api-guide/serializers.md | 2 ++ 1 file changed, 2 insertions(+) (limited to 'docs') diff --git a/docs/api-guide/serializers.md b/docs/api-guide/serializers.md index 6f1f2883..de2cf7d8 100644 --- a/docs/api-guide/serializers.md +++ b/docs/api-guide/serializers.md @@ -93,6 +93,8 @@ To serialize a queryset instead of an object instance, you should pass the `many When deserializing data, you always need to call `is_valid()` before attempting to access the deserialized object. If any validation errors occur, the `.errors` and `.non_field_errors` properties will contain the resulting error messages. +When deserialising a list of items, errors will be returned as a list of tuples. The first item in an error tuple will be the index of the item with the error in the original data; The second item in the tuple will be a dict with the individual errors for that item. + ### Field-level validation You can specify custom field-level validation by adding `.validate_` methods to your `Serializer` subclass. These are analagous to `.clean_` methods on Django forms, but accept slightly different arguments. -- cgit v1.2.3 From 1016c14a8a9eef1031c1a4000a2ae257775339d5 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Fri, 8 Mar 2013 20:26:10 +0000 Subject: Added @dulaccc. For the awesome OAuth 2 support in #693. --- 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 190ce490..0899632f 100644 --- a/docs/topics/credits.md +++ b/docs/topics/credits.md @@ -108,6 +108,7 @@ The following people have helped make REST framework great. * Omer Katz - [thedrow] * Wiliam Souza - [waa] * Jonas Braun - [iekadou] +* Pierre Dulac - [dulaccc] Many thanks to everyone who's contributed to the project. @@ -250,3 +251,4 @@ You can also contact [@_tomchristie][twitter] directly on twitter. [thedrow]: https://github.com/thedrow [waa]: https://github.com/wiliamsouza [iekadou]: https://github.com/iekadou +[dulaccc]: https://github.com/dulaccc -- cgit v1.2.3 From 4d48de631baee39025da04b95f46051d7398bd6c Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Fri, 8 Mar 2013 20:41:00 +0000 Subject: Docs on per-object filtering --- docs/api-guide/filtering.md | 8 ++++++++ docs/topics/release-notes.md | 4 ++++ 2 files changed, 12 insertions(+) (limited to 'docs') diff --git a/docs/api-guide/filtering.md b/docs/api-guide/filtering.md index 53ea7cbc..ed946368 100644 --- a/docs/api-guide/filtering.md +++ b/docs/api-guide/filtering.md @@ -140,6 +140,14 @@ For more details on using filter sets see the [django-filter documentation][djan --- +### Filtering and object lookups + +Note that if a filter backend is configured for a view, then as well as being used to filter list views, it will also be used to filter the querysets used for returning a single object. + +For instance, given the previous example, and a product with an id of `4675`, the following URL would either return the corresponding object, or return a 404 response, depending on if the filtering conditions were met by the given product instance: + + http://example.com/api/products/4675/?category=clothing&max_price=10.00 + ## Overriding the initial queryset Note that you can use both an overridden `.get_queryset()` and generic filtering together, and everything will work as expected. For example, if `Product` had a many-to-many relationship with `User`, named `purchase`, you might want to write a view like this: diff --git a/docs/topics/release-notes.md b/docs/topics/release-notes.md index 535da433..ab675950 100644 --- a/docs/topics/release-notes.md +++ b/docs/topics/release-notes.md @@ -40,6 +40,10 @@ You can determine your currently installed version using `pip freeze`: ## 2.2.x series +### Master + +* Filtering backends are now applied to the querysets for object lookups as well as lists. (Eg you can use a filtering backend to control which objects should 404) + ### 2.2.3 **Date**: 7th March 2013 -- cgit v1.2.3 From c5b98f0d106758298edf045e7bb44ecd7e4b9629 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Fri, 8 Mar 2013 20:56:30 +0000 Subject: authtoken abstract if not installed. Fixes #705. --- docs/topics/release-notes.md | 1 + 1 file changed, 1 insertion(+) (limited to 'docs') diff --git a/docs/topics/release-notes.md b/docs/topics/release-notes.md index ab675950..a4262d98 100644 --- a/docs/topics/release-notes.md +++ b/docs/topics/release-notes.md @@ -43,6 +43,7 @@ You can determine your currently installed version using `pip freeze`: ### Master * Filtering backends are now applied to the querysets for object lookups as well as lists. (Eg you can use a filtering backend to control which objects should 404) +* Bugfix: Workaround for Django bug causing case where `Authtoken` could be registered for cascade delete from `User` even if not installed. ### 2.2.3 -- cgit v1.2.3 From 0b6267d8cd45995585f0c02a4f9c96c0691fd32f Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Fri, 8 Mar 2013 22:28:59 +0000 Subject: Added @bitmonkey. Thanks! For work on handling errors when deserializing lists of objects. --- 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 190ce490..d6f312ed 100644 --- a/docs/topics/credits.md +++ b/docs/topics/credits.md @@ -108,6 +108,7 @@ The following people have helped make REST framework great. * Omer Katz - [thedrow] * Wiliam Souza - [waa] * Jonas Braun - [iekadou] +* Ian Dash - [bitmonkey] Many thanks to everyone who's contributed to the project. @@ -250,3 +251,4 @@ You can also contact [@_tomchristie][twitter] directly on twitter. [thedrow]: https://github.com/thedrow [waa]: https://github.com/wiliamsouza [iekadou]: https://github.com/iekadou +[bitmonkey]: https://github.com/bitmonkey -- cgit v1.2.3 From 6c1fcc855a2d05732113ce260b8660a414e1961e Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Fri, 8 Mar 2013 22:46:37 +0000 Subject: Update release notes --- docs/topics/release-notes.md | 1 + 1 file changed, 1 insertion(+) (limited to 'docs') diff --git a/docs/topics/release-notes.md b/docs/topics/release-notes.md index a4262d98..eb4d378e 100644 --- a/docs/topics/release-notes.md +++ b/docs/topics/release-notes.md @@ -43,6 +43,7 @@ You can determine your currently installed version using `pip freeze`: ### Master * Filtering backends are now applied to the querysets for object lookups as well as lists. (Eg you can use a filtering backend to control which objects should 404) +* Deal with error data nicely when deserializing lists of objects. * Bugfix: Workaround for Django bug causing case where `Authtoken` could be registered for cascade delete from `User` even if not installed. ### 2.2.3 -- cgit v1.2.3 From 69d169f5f629c1d02361198c4a76839a9f8d528d Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Fri, 8 Mar 2013 23:42:20 +0000 Subject: Neater override hooks and more docs for DjangoModelPermissions. Refs #702. --- docs/api-guide/permissions.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/api-guide/permissions.md b/docs/api-guide/permissions.md index 2db6ce1e..719ac1ef 100644 --- a/docs/api-guide/permissions.md +++ b/docs/api-guide/permissions.md @@ -90,12 +90,17 @@ This permission is suitable if you want to your API to allow read permissions to ## DjangoModelPermissions -This permission class ties into Django's standard `django.contrib.auth` [model permissions][contribauth]. When applied to a view that has a `.model` property, authorization will only be granted if the user has the relevant model permissions assigned. +This permission class ties into Django's standard `django.contrib.auth` [model permissions][contribauth]. When applied to a view that has a `.model` property, authorization will only be granted if the user *is authenticated* and has the *relevant model permissions* assigned. * `POST` requests require the user to have the `add` permission on the model. * `PUT` and `PATCH` requests require the user to have the `change` permission on the model. * `DELETE` requests require the user to have the `delete` permission on the model. +If you want to use `DjangoModelPermissions` but also allow unauthenticated users to have read permission, override the class and set the `authenticated_users_only` property to `False`. For example: + + class HasModelPermissionsOrReadOnly(DjangoModelPermissions): + authenticated_users_only = False + The default behaviour can also be overridden to support custom model permissions. For example, you might want to include a `view` model permission for `GET` requests. To use custom model permissions, override `DjangoModelPermissions` and set the `.perms_map` property. Refer to the source code for details. -- cgit v1.2.3 From 2c6c5d966e47fafbb9bace554ad14bd3b247aef9 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Fri, 8 Mar 2013 23:49:27 +0000 Subject: Update release notes. --- docs/topics/release-notes.md | 1 + 1 file changed, 1 insertion(+) (limited to 'docs') diff --git a/docs/topics/release-notes.md b/docs/topics/release-notes.md index eb4d378e..13235a82 100644 --- a/docs/topics/release-notes.md +++ b/docs/topics/release-notes.md @@ -44,6 +44,7 @@ You can determine your currently installed version using `pip freeze`: * Filtering backends are now applied to the querysets for object lookups as well as lists. (Eg you can use a filtering backend to control which objects should 404) * Deal with error data nicely when deserializing lists of objects. +* Extra override hook to configure `DjangoModelPermissions` for unauthenticated users. * Bugfix: Workaround for Django bug causing case where `Authtoken` could be registered for cascade delete from `User` even if not installed. ### 2.2.3 -- cgit v1.2.3 From a34f45b06e68fbe69f02d79c883ca764d88ac44b Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Sat, 9 Mar 2013 00:31:19 +0000 Subject: Docs polishing. --- docs/api-guide/authentication.md | 69 +++++++++++++++++++++++----------------- 1 file changed, 40 insertions(+), 29 deletions(-) (limited to 'docs') diff --git a/docs/api-guide/authentication.md b/docs/api-guide/authentication.md index 9234938c..541c6575 100644 --- a/docs/api-guide/authentication.md +++ b/docs/api-guide/authentication.md @@ -111,7 +111,7 @@ Unauthenticated responses that are denied permission will result in an `HTTP 401 ## TokenAuthentication -This authentication scheme uses a simple token-based HTTP Authentication scheme. Token authentication is appropriate for client-server setups, such as native desktop and mobile clients. +This authentication scheme 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` scheme, include `rest_framework.authtoken` in your `INSTALLED_APPS` setting: @@ -209,22 +209,30 @@ If you're using an AJAX style API with SessionAuthentication, you'll need to mak ## OAuthAuthentication -This authentication uses [OAuth 1.0a][oauth-1.0a] authentication scheme. It depends on the optional `django-oauth-plus` and `oauth2` packages. In order to make it work you must install these packages and add `oauth_provider` to your `INSTALLED_APPS`: +This authentication uses [OAuth 1.0a][oauth-1.0a] authentication scheme. OAuth 1.0a provides signature validation which provides a reasonable level of security over plain non-HTTPS connections. However, it may also be considered more complicated than OAuth2, as it requires clients to sign their requests. + +This authentication class depends on the optional `django-oauth-plus` and `oauth2` packages. In order to make it work you must install these packages and add `oauth_provider` to your `INSTALLED_APPS`: INSTALLED_APPS = ( ... `oauth_provider`, ) -OAuthAuthentication class provides only token verification and signature validation for requests. It doesn't provide authorization flow for your clients. You still need to implement your own views for accessing and authorizing Reqest/Access Tokens. This is because there are many different OAuth flows in use. Almost always they require end-user interaction, and most likely this is what you want to design yourself. +Don't forget to run `syncdb` once you've added the package. + + python manage.py syncdb #### Getting started with django-oauth-plus -The `django-oauth-plus` package provides simple foundation for classic 'three-legged' oauth flow, so if it is what you need please refer to [its documentation][django-oauth-plus]. This documentation will provide you also information about how to work with supplied models and change basic settings. +The OAuthAuthentication class only provides token verification and signature validation for requests. It doesn't provide authorization flow for your clients. You still need to implement your own views for accessing and authorizing tokens. + +The `django-oauth-plus` package provides simple foundation for classic 'three-legged' oauth flow. Please refer to [the documentation][django-oauth-plus] for more details. ## OAuth2Authentication -This authentication uses [OAuth 2.0][rfc6749] authentication scheme. It depends on the optional [django-oauth2-provider][django-oauth2-provider] project. In order to make it work you must install this package and add `provider` and `provider.oauth2` to your `INSTALLED_APPS` : +This authentication uses [OAuth 2.0][rfc6749] authentication scheme. OAuth2 is more simple to work with than OAuth1, and provides much better security than simple token authentication. It is an unauthenticated scheme, and requires you to use an HTTPS connection. + +This authentication class depends on the optional [django-oauth2-provider][django-oauth2-provider] project. In order to make it work you must install this package and add `provider` and `provider.oauth2` to your `INSTALLED_APPS`: INSTALLED_APPS = ( ... @@ -232,57 +240,61 @@ This authentication uses [OAuth 2.0][rfc6749] authentication scheme. It depends 'provider.oauth2', ) -And include the urls needed in your root `urls.py` file to be able to begin the *oauth 2 dance* : +You must also include the following in your root `urls.py` module: url(r'^oauth2/', include('provider.oauth2.urls', namespace='oauth2')), -**Note**: The `namespace` argument is required +Note that the `namespace='oauth2'` argument is required. -Finally, sync your database with those two new django apps. +Finally, sync your database. - $ python manage.py syncdb - $ python manage.py migrate + python manage.py syncdb + python manage.py migrate -`OAuth2Authentication` class provides only token verification for requests. The *oauth 2 dance* is taken care by the [django-oaut2-provider][django-oauth2-provider] dependency. The official [documentation][django-oauth2-provider--doc] is being [rewritten][django-oauth2-provider--rewritten-doc]. +--- + +**Note:** If you use `OAuth2Authentication` in production you must ensure that your API is only available over `https` only. -The Good news is, here is a minimal "How to start" because **OAuth 2** is dramatically simpler than **OAuth 1**, so no more headache with signature, cryptography on client side, and other complex things. +--- #### Getting started with django-oauth2-provider -1. Create a client in the django-admin panel +The `OAuth2Authentication` class only provides token verification for requests. It doesn't provide authorization flow for your clients. + +The OAuth 2 authorization flow is taken care by the [django-oauth2-provider][django-oauth2-provider] dependency. A walkthrough is given here, but for more details you should refer to [the documentation][django-oauth2-provider-docs]. + +To get started: + +##### 1. Create a client + +You can create a client, either through the shell, or by using the Django admin. Go to the admin panel and create a new `Provider.Client` entry. It will create the `client_id` and `client_secret` properties for you. -2. Request an access token +##### 2. Request an access token -To request an access toke, submit a `POST` request to the url `/oauth2/access_token` with the following fields : +To request an access token, submit a `POST` request to the url `/oauth2/access_token` with the following fields: * `client_id` the client id you've just configured at the previous step. * `client_secret` again configured at the previous step. * `username` the username with which you want to log in. * `password` well, that speaks for itself. ---- - -**Note:** Remember that you should use HTTPS in production. - ---- - -You can use the command line to test that your local configuration is working : +You can use the command line to test that your local configuration is working: - $ curl -X POST -d "client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET&grant_type=password&username=YOUR_USERNAME&password=YOUR_PASSWORD" http://localhost:8000/oauth2/access_token/ + curl -X POST -d "client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET&grant_type=password&username=YOUR_USERNAME&password=YOUR_PASSWORD" http://localhost:8000/oauth2/access_token/ -Here is the response you should get : +You should get a response that looks something like this: {"access_token": "", "scope": "read", "expires_in": 86399, "refresh_token": ""} -3. Access the api +##### 3. Access the API -The only thing needed to make the `OAuth2Authentication` class work is to insert the `access_token` you've received in the `Authorization` api request header. +The only thing needed to make the `OAuth2Authentication` class work is to insert the `access_token` you've received in the `Authorization` request header. The command line to test the authentication looks like: - $ curl -H "Authorization: Bearer " http://localhost:8000/api/?client_id=YOUR_CLIENT_ID\&client_secret=YOUR_CLIENT_SECRET + curl -H "Authorization: Bearer " http://localhost:8000/api/?client_id=YOUR_CLIENT_ID\&client_secret=YOUR_CLIENT_SECRET --- @@ -344,6 +356,5 @@ HTTP digest authentication is a widely implemented scheme that was intended to r [oauth-1.0a]: http://oauth.net/core/1.0a [django-oauth-plus]: http://code.larlet.fr/django-oauth-plus [django-oauth2-provider]: https://github.com/caffeinehit/django-oauth2-provider -[django-oauth2-provider--doc]: https://django-oauth2-provider.readthedocs.org/en/latest/ -[django-oauth2-provider--rewritten-doc]: http://django-oauth2-provider-dulaccc.readthedocs.org/en/latest/ +[django-oauth2-provider-docs]: https://django-oauth2-provider.readthedocs.org/en/latest/ [rfc6749]: http://tools.ietf.org/html/rfc6749 -- cgit v1.2.3 From 0df008dc83cacc0ac1aef8f915c3d764b6c4e498 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Sun, 10 Mar 2013 20:37:15 +0000 Subject: Added @bouke for bug fix #722. Thanks! --- docs/topics/credits.md | 3 +++ 1 file changed, 3 insertions(+) (limited to 'docs') diff --git a/docs/topics/credits.md b/docs/topics/credits.md index d6f312ed..35a302fd 100644 --- a/docs/topics/credits.md +++ b/docs/topics/credits.md @@ -109,6 +109,7 @@ The following people have helped make REST framework great. * Wiliam Souza - [waa] * Jonas Braun - [iekadou] * Ian Dash - [bitmonkey] +* Bouke Haarsma - [bouke] Many thanks to everyone who's contributed to the project. @@ -252,3 +253,5 @@ You can also contact [@_tomchristie][twitter] directly on twitter. [waa]: https://github.com/wiliamsouza [iekadou]: https://github.com/iekadou [bitmonkey]: https://github.com/bitmonkey +[bouke]: https://github.com/bouke + -- cgit v1.2.3 From 20880232930dd6f3a1de9dda1546c84b9279a258 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Sun, 10 Mar 2013 20:39:04 +0000 Subject: Update release notes --- docs/topics/release-notes.md | 1 + 1 file changed, 1 insertion(+) (limited to 'docs') diff --git a/docs/topics/release-notes.md b/docs/topics/release-notes.md index 13235a82..ff487826 100644 --- a/docs/topics/release-notes.md +++ b/docs/topics/release-notes.md @@ -45,6 +45,7 @@ You can determine your currently installed version using `pip freeze`: * Filtering backends are now applied to the querysets for object lookups as well as lists. (Eg you can use a filtering backend to control which objects should 404) * Deal with error data nicely when deserializing lists of objects. * Extra override hook to configure `DjangoModelPermissions` for unauthenticated users. +* Bugfix: Fix pk relationship bug for some types of 1-to-1 relations. * Bugfix: Workaround for Django bug causing case where `Authtoken` could be registered for cascade delete from `User` even if not installed. ### 2.2.3 -- cgit v1.2.3 From 2bcb8ff12c967e71fb4871a9ac9e72395394d291 Mon Sep 17 00:00:00 2001 From: Dave Kuhn Date: Tue, 12 Mar 2013 13:48:40 +1100 Subject: Documentation for X-HTTP-Method-Override --- docs/topics/browser-enhancements.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'docs') diff --git a/docs/topics/browser-enhancements.md b/docs/topics/browser-enhancements.md index 6a11f0fa..8b191423 100644 --- a/docs/topics/browser-enhancements.md +++ b/docs/topics/browser-enhancements.md @@ -19,6 +19,23 @@ For example, given the following form: `request.method` would return `"DELETE"`. +## HTTP header based method overriding + +REST framework also supports method overriding via the `X-HTTP-Method-Override` +header. This is useful if you are working with non-form content such as +JSON and are working with an older web server and/or hosting provider +(e.g. [Amazon Web Services ELB][aws_elb]) that doesn't recognise particular +HTTP methods such as `PATCH`. + +For example, making a `PATCH` request via `POST` in jQuery: + + $.ajax({ + url: '/myresource/', + method: 'POST', + headers: {'X-HTTP-Method-Override': 'PATCH'}, + ... + }); + ## Browser based submission of non-form content Browser-based submission of content types other than form are supported by @@ -62,3 +79,4 @@ as well as how to support content types other than form-encoded data. [rails]: http://guides.rubyonrails.org/form_helpers.html#how-do-forms-with-put-or-delete-methods-work [html5]: http://www.w3.org/TR/html5-diff/#changes-2010-06-24 [put_delete]: http://amundsen.com/examples/put-delete-forms/ +[aws_elb]: https://forums.aws.amazon.com/thread.jspa?messageID=400724 -- cgit v1.2.3 From a574dc7f85e09b4c0096d7b1c12a8e525ea8e31f Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Tue, 12 Mar 2013 20:12:22 +0000 Subject: Update release notes --- docs/topics/release-notes.md | 2 ++ 1 file changed, 2 insertions(+) (limited to 'docs') diff --git a/docs/topics/release-notes.md b/docs/topics/release-notes.md index ff487826..ac201e20 100644 --- a/docs/topics/release-notes.md +++ b/docs/topics/release-notes.md @@ -42,6 +42,8 @@ You can determine your currently installed version using `pip freeze`: ### Master +* OAuth 2 support. +* OAuth 1.0a support. * Filtering backends are now applied to the querysets for object lookups as well as lists. (Eg you can use a filtering backend to control which objects should 404) * Deal with error data nicely when deserializing lists of objects. * Extra override hook to configure `DjangoModelPermissions` for unauthenticated users. -- cgit v1.2.3 From 377dc2cda2c3a7aa02f5d761631f73c58745ed9d Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Tue, 12 Mar 2013 20:49:20 +0000 Subject: Only honor X-HTTP-Method-Override for POST requests. --- docs/topics/browser-enhancements.md | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'docs') diff --git a/docs/topics/browser-enhancements.md b/docs/topics/browser-enhancements.md index 8b191423..ce07fe95 100644 --- a/docs/topics/browser-enhancements.md +++ b/docs/topics/browser-enhancements.md @@ -21,11 +21,9 @@ For example, given the following form: ## HTTP header based method overriding -REST framework also supports method overriding via the `X-HTTP-Method-Override` -header. This is useful if you are working with non-form content such as -JSON and are working with an older web server and/or hosting provider -(e.g. [Amazon Web Services ELB][aws_elb]) that doesn't recognise particular -HTTP methods such as `PATCH`. +REST framework also supports method overriding via the semi-standard `X-HTTP-Method-Override` header. This can be useful if you are working with non-form content such as JSON and are working with an older web server and/or hosting provider that doesn't recognise particular HTTP methods such as `PATCH`. For example [Amazon Web Services ELB][aws_elb]. + +To use it, make a `POST` request, setting the `X-HTTP-Method-Override` header. For example, making a `PATCH` request via `POST` in jQuery: -- cgit v1.2.3 From 208407d569b4c794f7ea6ec114b662b6faf56845 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Tue, 12 Mar 2013 20:49:44 +0000 Subject: Update release notes. --- docs/topics/release-notes.md | 1 + 1 file changed, 1 insertion(+) (limited to 'docs') diff --git a/docs/topics/release-notes.md b/docs/topics/release-notes.md index ac201e20..d0b46c36 100644 --- a/docs/topics/release-notes.md +++ b/docs/topics/release-notes.md @@ -44,6 +44,7 @@ You can determine your currently installed version using `pip freeze`: * OAuth 2 support. * OAuth 1.0a support. +* Support X-HTTP-Method-Override header. * Filtering backends are now applied to the querysets for object lookups as well as lists. (Eg you can use a filtering backend to control which objects should 404) * Deal with error data nicely when deserializing lists of objects. * Extra override hook to configure `DjangoModelPermissions` for unauthenticated users. -- cgit v1.2.3 From 1aecd71eb49111009f2c55fe8bd3901b3ea35dd5 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Tue, 12 Mar 2013 20:52:04 +0000 Subject: Added @kuhnza for work on #695. 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 b0f0cfa2..b533daa9 100644 --- a/docs/topics/credits.md +++ b/docs/topics/credits.md @@ -111,6 +111,7 @@ The following people have helped make REST framework great. * Ian Dash - [bitmonkey] * Bouke Haarsma - [bouke] * Pierre Dulac - [dulaccc] +* Dave Kuhn - [kuhnza] Many thanks to everyone who's contributed to the project. @@ -256,3 +257,4 @@ You can also contact [@_tomchristie][twitter] directly on twitter. [bitmonkey]: https://github.com/bitmonkey [bouke]: https://github.com/bouke [dulaccc]: https://github.com/dulaccc +[kuhnza]: https://github.com/kuhnza -- cgit v1.2.3 From a798a5350a6aa3100695d41d4d37ec7e2e073bdd Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Wed, 13 Mar 2013 11:42:12 +0000 Subject: Fix duplicated database queries for paginated lists. Closes #713. --- docs/topics/release-notes.md | 1 + 1 file changed, 1 insertion(+) (limited to 'docs') diff --git a/docs/topics/release-notes.md b/docs/topics/release-notes.md index d0b46c36..4eaa42ba 100644 --- a/docs/topics/release-notes.md +++ b/docs/topics/release-notes.md @@ -48,6 +48,7 @@ You can determine your currently installed version using `pip freeze`: * Filtering backends are now applied to the querysets for object lookups as well as lists. (Eg you can use a filtering backend to control which objects should 404) * Deal with error data nicely when deserializing lists of objects. * Extra override hook to configure `DjangoModelPermissions` for unauthenticated users. +* Bugfix: Fix regression which caused extra database query on paginated list views. * Bugfix: Fix pk relationship bug for some types of 1-to-1 relations. * Bugfix: Workaround for Django bug causing case where `Authtoken` could be registered for cascade delete from `User` even if not installed. -- cgit v1.2.3 From 4b68089d44d3ede878eff58f6e3cdad86f5c832e Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Wed, 13 Mar 2013 13:07:46 +0000 Subject: Version 2.2.4 --- docs/topics/release-notes.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/topics/release-notes.md b/docs/topics/release-notes.md index 4eaa42ba..5a96c09c 100644 --- a/docs/topics/release-notes.md +++ b/docs/topics/release-notes.md @@ -40,7 +40,9 @@ You can determine your currently installed version using `pip freeze`: ## 2.2.x series -### Master +### 2.2.4 + +**Date**: 13th March 2013 * OAuth 2 support. * OAuth 1.0a support. -- cgit v1.2.3 From a53596ce28359e24313a5fb9bd8f3564eb12678e Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Wed, 13 Mar 2013 13:13:30 +0000 Subject: Docs for TokenHasReadWriteScope --- docs/api-guide/permissions.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'docs') diff --git a/docs/api-guide/permissions.md b/docs/api-guide/permissions.md index 719ac1ef..4772c5e0 100644 --- a/docs/api-guide/permissions.md +++ b/docs/api-guide/permissions.md @@ -105,6 +105,21 @@ The default behaviour can also be overridden to support custom model permissions To use custom model permissions, override `DjangoModelPermissions` and set the `.perms_map` property. Refer to the source code for details. +## TokenHasReadWriteScope + +This permission class is intended for use with either of the `OAuthAuthentication` and `OAuth2Authentication` classes, and ties into the scoping that their backends provide. + +Requests with a safe methods of `GET`, `OPTIONS` or `HEAD` will be allowed if the authenticated token has read permission. + +Requests for `POST`, `PUT`, `PATCH` and `DELETE` will be allowed if the authenticated token has write permission. + +This permission class relies on the implementations of the [django-oauth-plus][django-oauth-plus] and [django-oauth2-provider][django-oauth2-provider] libraries, which both provide limited support for controlling the scope of access tokens: + +* `django-oauth-plus`: Tokens are associated with a `Resource` class which has a `name`, `url` and `is_readonly` properties. +* `django-oauth2-provider`: Tokens are associated with a bitwise `scope` attribute, that defaults to providing bitwise values for `read` and/or `write`. + +If you require more advanced scoping for your API, such as restricting tokens to accessing a subset of functionality of your API then you will need to provide a custom permission class. See the source of the `django-oauth-plus` or `django-oauth2-provider` package for more details on scoping token access. + --- # Custom permissions @@ -173,5 +188,7 @@ Also note that the generic views will only check the object-level permissions fo [throttling]: throttling.md [contribauth]: https://docs.djangoproject.com/en/1.0/topics/auth/#permissions [guardian]: https://github.com/lukaszb/django-guardian +[django-oauth-plus]: http://code.larlet.fr/django-oauth-plus +[django-oauth2-provider]: https://github.com/caffeinehit/django-oauth2-provider [2.2-announcement]: ../topics/2.2-announcement.md [filtering]: filtering.md -- cgit v1.2.3 From acc8c1faa4f85dda00723d755e56bb3c980dbc75 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Wed, 13 Mar 2013 20:40:39 +0000 Subject: force_insert, force_update arguments. Closes #484. Confirmed by `assertNumQueries(…)` in tests. --- docs/topics/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'docs') diff --git a/docs/topics/release-notes.md b/docs/topics/release-notes.md index 5a96c09c..c45fff88 100644 --- a/docs/topics/release-notes.md +++ b/docs/topics/release-notes.md @@ -40,6 +40,10 @@ You can determine your currently installed version using `pip freeze`: ## 2.2.x series +### Master + +* `Serializer.save()` now supports arbitrary keyword args which are passed through to the object `.save()` method. Mixins use `force_insert` and `force_update` where appropriate, resulting in one less database query. + ### 2.2.4 **Date**: 13th March 2013 -- cgit v1.2.3 From 08bc203f905f838fdcc2f7cc09b91eab4e595bd1 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Wed, 13 Mar 2013 20:53:39 +0000 Subject: Docs tweaks. --- docs/index.md | 6 +++--- docs/template.html | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'docs') diff --git a/docs/index.md b/docs/index.md index 8e5097b3..5f9d1553 100644 --- a/docs/index.md +++ b/docs/index.md @@ -9,9 +9,9 @@ # Django REST framework -**A toolkit for building well-connected, self-describing Web APIs.** +**Web APIs for Django, made easy.** -Django REST framework is a lightweight library that makes it easy to build Web APIs. It is designed as a modular and easy to customize architecture, based on Django's class based views. +Django REST framework is a flexible, powerful library that makes it incredibly easy to build Web APIs. It is designed as a modular and easy to customize architecture, based on Django's class based views. Web APIs built using REST framework are fully self-describing and web browseable - a huge useability win for your developers. It also supports a wide range of media types, authentication and permission policies out of the box. @@ -75,7 +75,7 @@ Note that the URL path can be whatever you want, but you must include `'rest_fra ## Quickstart -Can't wait to get started? The [quickstart guide][quickstart] is the fastest way to get up and running with REST framework. +Can't wait to get started? The [quickstart guide][quickstart] is the fastest way to get up and running, and building APIs with REST framework. ## Tutorial diff --git a/docs/template.html b/docs/template.html index e0f88daf..08620882 100644 --- a/docs/template.html +++ b/docs/template.html @@ -2,7 +2,7 @@ - Django REST framework + Django REST framework - APIs made easy. -- cgit v1.2.3 From da76bd704726830b0b76aabe7aef91b2deb72b02 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Wed, 13 Mar 2013 20:56:16 +0000 Subject: Tweak text. --- docs/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/index.md b/docs/index.md index 5f9d1553..5357536d 100644 --- a/docs/index.md +++ b/docs/index.md @@ -13,7 +13,7 @@ Django REST framework is a flexible, powerful library that makes it incredibly easy to build Web APIs. It is designed as a modular and easy to customize architecture, based on Django's class based views. -Web APIs built using REST framework are fully self-describing and web browseable - a huge useability win for your developers. It also supports a wide range of media types, authentication and permission policies out of the box. +APIs built using REST framework are fully self-describing and web browseable - a huge useability win for your developers. It also supports a wide range of media types, authentication and permission policies out of the box. If you are considering using REST framework for your API, we recommend reading the [REST framework 2 announcement][rest-framework-2-announcement] which gives a good overview of the framework and it's capabilities. -- cgit v1.2.3 From 22a389d0ba4dd5ac7b4fa3839491ec2708bbe7df Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Fri, 15 Mar 2013 13:41:22 +0000 Subject: Better titles & descriptions --- docs/template.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'docs') diff --git a/docs/template.html b/docs/template.html index 08620882..3e0f29aa 100644 --- a/docs/template.html +++ b/docs/template.html @@ -2,11 +2,11 @@ - Django REST framework - APIs made easy. + {{ title }} - - + + -- cgit v1.2.3 From e80d3d1bdfb071a288340555cb6fe8a9bce3772d Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Sun, 17 Mar 2013 19:51:04 +0000 Subject: Fix text regarding serializer error messages. Closes #734.--- docs/api-guide/serializers.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'docs') diff --git a/docs/api-guide/serializers.md b/docs/api-guide/serializers.md index de2cf7d8..e7e1670b 100644 --- a/docs/api-guide/serializers.md +++ b/docs/api-guide/serializers.md @@ -91,9 +91,10 @@ To serialize a queryset instead of an object instance, you should pass the `many ## Validation -When deserializing data, you always need to call `is_valid()` before attempting to access the deserialized object. If any validation errors occur, the `.errors` and `.non_field_errors` properties will contain the resulting error messages. +When deserializing data, you always need to call `is_valid()` before attempting to access the deserialized object. If any validation errors occur, the `.errors` property will contain a dictionary representing the resulting error messages. +Each key in the dictionary will be the field name, and the values will be lists of strings of any error messages corresponding to that field. The `non_field_errors` key may also be present, and will list any general validation errors. -When deserialising a list of items, errors will be returned as a list of tuples. The first item in an error tuple will be the index of the item with the error in the original data; The second item in the tuple will be a dict with the individual errors for that item. +When deserializing a list of items, errors will be returned as a list of dictionaries representing each of the deserialized items. ### Field-level validation -- cgit v1.2.3 From ef0caf64d326bacdf367e002e5537b8c0d444d34 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Sun, 17 Mar 2013 19:59:13 +0000 Subject: Extra note on method --- docs/api-guide/serializers.md | 8 ++++++++ docs/tutorial/1-serialization.md | 6 +++++- 2 files changed, 13 insertions(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/api-guide/serializers.md b/docs/api-guide/serializers.md index e7e1670b..e8d3c1b5 100644 --- a/docs/api-guide/serializers.md +++ b/docs/api-guide/serializers.md @@ -25,6 +25,7 @@ Let's start by creating a simple object we can use for example purposes: comment = Comment(email='leila@example.com', content='foo bar') We'll declare a serializer that we can use to serialize and deserialize `Comment` objects. + Declaring a serializer looks very similar to declaring a form: class CommentSerializer(serializers.Serializer): @@ -33,6 +34,13 @@ Declaring a serializer looks very similar to declaring a form: created = serializers.DateTimeField() def restore_object(self, attrs, instance=None): + """ + Given a dictionary of deserialized field values, either update + an existing model instance, or create a new model instance. + + Note that if we don't define this method, then deserializing + data will simply return a dictionary of items. + """ if instance is not None: instance.title = attrs['title'] instance.content = attrs['content'] diff --git a/docs/tutorial/1-serialization.md b/docs/tutorial/1-serialization.md index 6709f751..205ee7e0 100644 --- a/docs/tutorial/1-serialization.md +++ b/docs/tutorial/1-serialization.md @@ -126,7 +126,11 @@ The first thing we need to get started on our Web API is provide a way of serial def restore_object(self, attrs, instance=None): """ - Create or update a new snippet instance. + Create or update a new snippet instance, given a dictionary + of deserialized field values. + + Note that if we don't define this method, then deserializing + data will simply return a dictionary of items. """ if instance: # Update existing instance -- cgit v1.2.3 From 034c4ce4081dd6d15ea47fb8318754321a3faf0c Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Sun, 17 Mar 2013 20:06:38 +0000 Subject: Fix serializer restore_object example for partial updates --- docs/api-guide/serializers.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'docs') diff --git a/docs/api-guide/serializers.md b/docs/api-guide/serializers.md index e8d3c1b5..42edf9af 100644 --- a/docs/api-guide/serializers.md +++ b/docs/api-guide/serializers.md @@ -42,9 +42,9 @@ Declaring a serializer looks very similar to declaring a form: data will simply return a dictionary of items. """ if instance is not None: - instance.title = attrs['title'] - instance.content = attrs['content'] - instance.created = attrs['created'] + instance.title = attrs.get('title', instance.title) + instance.content = attrs.get('content', instance.content) + instance.created = attrs.get('created', instance.created) return instance return Comment(**attrs) -- cgit v1.2.3