diff options
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/404.html | 104 | ||||
| -rwxr-xr-x | docs/api-guide/authentication.md | 34 | ||||
| -rw-r--r-- | docs/api-guide/exceptions.md | 6 | ||||
| -rw-r--r-- | docs/api-guide/fields.md | 44 | ||||
| -rw-r--r-- | docs/api-guide/filtering.md | 38 | ||||
| -rwxr-xr-x | docs/api-guide/generic-views.md | 13 | ||||
| -rw-r--r-- | docs/api-guide/pagination.md | 10 | ||||
| -rw-r--r-- | docs/api-guide/relations.md | 5 | ||||
| -rw-r--r-- | docs/api-guide/routers.md | 14 | ||||
| -rw-r--r-- | docs/api-guide/serializers.md | 50 | ||||
| -rw-r--r-- | docs/api-guide/settings.md | 18 | ||||
| -rw-r--r-- | docs/api-guide/testing.md | 4 | ||||
| -rw-r--r-- | docs/api-guide/throttling.md | 2 | ||||
| -rw-r--r-- | docs/api-guide/viewsets.md | 2 | ||||
| -rw-r--r-- | docs/img/logo.png | bin | 0 -> 41532 bytes | |||
| -rw-r--r-- | docs/index.md | 71 | ||||
| -rw-r--r-- | docs/template.html | 27 | ||||
| -rw-r--r-- | docs/topics/2.2-announcement.md | 2 | ||||
| -rw-r--r-- | docs/topics/contributing.md | 20 | ||||
| -rw-r--r-- | docs/topics/credits.md | 2 | ||||
| -rw-r--r-- | docs/topics/release-notes.md | 39 | ||||
| -rw-r--r-- | docs/tutorial/1-serialization.md | 5 | ||||
| -rw-r--r-- | docs/tutorial/4-authentication-and-permissions.md | 2 | 
23 files changed, 349 insertions, 163 deletions
| diff --git a/docs/404.html b/docs/404.html index 4938da6e..864247e7 100644 --- a/docs/404.html +++ b/docs/404.html @@ -3,17 +3,17 @@  <head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">      <meta charset="utf-8">      <title>Django REST framework - 404 - Page not found</title> -    <link href="http://django-rest-framework.org/img/favicon.ico" rel="icon" type="image/x-icon"> -    <link rel="canonical" href="http://django-rest-framework.org/404"/> +    <link href="http://www.django-rest-framework.org/img/favicon.ico" rel="icon" type="image/x-icon"> +    <link rel="canonical" href="http://www.django-rest-framework.org/404"/>      <meta name="viewport" content="width=device-width, initial-scale=1.0">      <meta name="description" content="Django, API, REST, 404 - Page not found">      <meta name="author" content="Tom Christie">      <!-- Le styles --> -    <link href="http://django-rest-framework.org/css/prettify.css" rel="stylesheet"> -    <link href="http://django-rest-framework.org/css/bootstrap.css" rel="stylesheet"> -    <link href="http://django-rest-framework.org/css/bootstrap-responsive.css" rel="stylesheet"> -    <link href="http://django-rest-framework.org/css/default.css" rel="stylesheet"> +    <link href="http://www.django-rest-framework.org/css/prettify.css" rel="stylesheet"> +    <link href="http://www.django-rest-framework.org/css/bootstrap.css" rel="stylesheet"> +    <link href="http://www.django-rest-framework.org/css/bootstrap-responsive.css" rel="stylesheet"> +    <link href="http://www.django-rest-framework.org/css/default.css" rel="stylesheet">      <!-- Le HTML5 shim, for IE6-8 support of HTML5 elements -->      <!--[if lt IE 9]> @@ -50,63 +50,63 @@              <span class="icon-bar"></span>              <span class="icon-bar"></span>            </a> -          <a class="brand" href="http://django-rest-framework.org">Django REST framework</a> +          <a class="brand" href="http://www.django-rest-framework.org">Django REST framework</a>            <div class="nav-collapse collapse">              <ul class="nav"> -              <li><a href="http://django-rest-framework.org">Home</a></li> +              <li><a href="http://www.django-rest-framework.org">Home</a></li>                <li class="dropdown">                  <a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorial <b class="caret"></b></a>                  <ul class="dropdown-menu"> -                  <li><a href="http://django-rest-framework.org/tutorial/quickstart">Quickstart</a></li> -                  <li><a href="http://django-rest-framework.org/tutorial/1-serialization">1 - Serialization</a></li> -                  <li><a href="http://django-rest-framework.org/tutorial/2-requests-and-responses">2 - Requests and responses</a></li> -                  <li><a href="http://django-rest-framework.org/tutorial/3-class-based-views">3 - Class based views</a></li> -                  <li><a href="http://django-rest-framework.org/tutorial/4-authentication-and-permissions">4 - Authentication and permissions</a></li> -                  <li><a href="http://django-rest-framework.org/tutorial/5-relationships-and-hyperlinked-apis">5 - Relationships and hyperlinked APIs</a></li> -                  <li><a href="http://django-rest-framework.org/tutorial/6-viewsets-and-routers">6 - Viewsets and routers</a></li> +                  <li><a href="http://www.django-rest-framework.org/tutorial/quickstart">Quickstart</a></li> +                  <li><a href="http://www.django-rest-framework.org/tutorial/1-serialization">1 - Serialization</a></li> +                  <li><a href="http://www.django-rest-framework.org/tutorial/2-requests-and-responses">2 - Requests and responses</a></li> +                  <li><a href="http://www.django-rest-framework.org/tutorial/3-class-based-views">3 - Class based views</a></li> +                  <li><a href="http://www.django-rest-framework.org/tutorial/4-authentication-and-permissions">4 - Authentication and permissions</a></li> +                  <li><a href="http://www.django-rest-framework.org/tutorial/5-relationships-and-hyperlinked-apis">5 - Relationships and hyperlinked APIs</a></li> +                  <li><a href="http://www.django-rest-framework.org/tutorial/6-viewsets-and-routers">6 - Viewsets and routers</a></li>                  </ul>                </li>                <li class="dropdown">                  <a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>                  <ul class="dropdown-menu"> -                  <li><a href="http://django-rest-framework.org/api-guide/requests">Requests</a></li> -                  <li><a href="http://django-rest-framework.org/api-guide/responses">Responses</a></li> -                  <li><a href="http://django-rest-framework.org/api-guide/views">Views</a></li> -                  <li><a href="http://django-rest-framework.org/api-guide/generic-views">Generic views</a></li> -                  <li><a href="http://django-rest-framework.org/api-guide/viewsets">Viewsets</a></li> -                  <li><a href="http://django-rest-framework.org/api-guide/routers">Routers</a></li> -                  <li><a href="http://django-rest-framework.org/api-guide/parsers">Parsers</a></li> -                  <li><a href="http://django-rest-framework.org/api-guide/renderers">Renderers</a></li> -                  <li><a href="http://django-rest-framework.org/api-guide/serializers">Serializers</a></li> -                  <li><a href="http://django-rest-framework.org/api-guide/fields">Serializer fields</a></li> -                  <li><a href="http://django-rest-framework.org/api-guide/relations">Serializer relations</a></li> -                  <li><a href="http://django-rest-framework.org/api-guide/authentication">Authentication</a></li> -                  <li><a href="http://django-rest-framework.org/api-guide/permissions">Permissions</a></li> -                  <li><a href="http://django-rest-framework.org/api-guide/throttling">Throttling</a></li> -                  <li><a href="http://django-rest-framework.org/api-guide/filtering">Filtering</a></li> -                  <li><a href="http://django-rest-framework.org/api-guide/pagination">Pagination</a></li> -                  <li><a href="http://django-rest-framework.org/api-guide/content-negotiation">Content negotiation</a></li> -                  <li><a href="http://django-rest-framework.org/api-guide/format-suffixes">Format suffixes</a></li> -                  <li><a href="http://django-rest-framework.org/api-guide/reverse">Returning URLs</a></li> -                  <li><a href="http://django-rest-framework.org/api-guide/exceptions">Exceptions</a></li> -                  <li><a href="http://django-rest-framework.org/api-guide/status-codes">Status codes</a></li> -                  <li><a href="http://django-rest-framework.org/api-guide/testing">Testing</a></li> -                  <li><a href="http://django-rest-framework.org/api-guide/settings">Settings</a></li> +                  <li><a href="http://www.django-rest-framework.org/api-guide/requests">Requests</a></li> +                  <li><a href="http://www.django-rest-framework.org/api-guide/responses">Responses</a></li> +                  <li><a href="http://www.django-rest-framework.org/api-guide/views">Views</a></li> +                  <li><a href="http://www.django-rest-framework.org/api-guide/generic-views">Generic views</a></li> +                  <li><a href="http://www.django-rest-framework.org/api-guide/viewsets">Viewsets</a></li> +                  <li><a href="http://www.django-rest-framework.org/api-guide/routers">Routers</a></li> +                  <li><a href="http://www.django-rest-framework.org/api-guide/parsers">Parsers</a></li> +                  <li><a href="http://www.django-rest-framework.org/api-guide/renderers">Renderers</a></li> +                  <li><a href="http://www.django-rest-framework.org/api-guide/serializers">Serializers</a></li> +                  <li><a href="http://www.django-rest-framework.org/api-guide/fields">Serializer fields</a></li> +                  <li><a href="http://www.django-rest-framework.org/api-guide/relations">Serializer relations</a></li> +                  <li><a href="http://www.django-rest-framework.org/api-guide/authentication">Authentication</a></li> +                  <li><a href="http://www.django-rest-framework.org/api-guide/permissions">Permissions</a></li> +                  <li><a href="http://www.django-rest-framework.org/api-guide/throttling">Throttling</a></li> +                  <li><a href="http://www.django-rest-framework.org/api-guide/filtering">Filtering</a></li> +                  <li><a href="http://www.django-rest-framework.org/api-guide/pagination">Pagination</a></li> +                  <li><a href="http://www.django-rest-framework.org/api-guide/content-negotiation">Content negotiation</a></li> +                  <li><a href="http://www.django-rest-framework.org/api-guide/format-suffixes">Format suffixes</a></li> +                  <li><a href="http://www.django-rest-framework.org/api-guide/reverse">Returning URLs</a></li> +                  <li><a href="http://www.django-rest-framework.org/api-guide/exceptions">Exceptions</a></li> +                  <li><a href="http://www.django-rest-framework.org/api-guide/status-codes">Status codes</a></li> +                  <li><a href="http://www.django-rest-framework.org/api-guide/testing">Testing</a></li> +                  <li><a href="http://www.django-rest-framework.org/api-guide/settings">Settings</a></li>                  </ul>                </li>                <li class="dropdown">                  <a href="#" class="dropdown-toggle" data-toggle="dropdown">Topics <b class="caret"></b></a>                  <ul class="dropdown-menu"> -                  <li><a href="http://django-rest-framework.org/topics/documenting-your-api">Documenting your API</a></li> -                  <li><a href="http://django-rest-framework.org/topics/ajax-csrf-cors">AJAX, CSRF & CORS</a></li> -                  <li><a href="http://django-rest-framework.org/topics/browser-enhancements">Browser enhancements</a></li> -                  <li><a href="http://django-rest-framework.org/topics/browsable-api">The Browsable API</a></li> -                  <li><a href="http://django-rest-framework.org/topics/rest-hypermedia-hateoas">REST, Hypermedia & HATEOAS</a></li> -                  <li><a href="http://django-rest-framework.org/topics/rest-framework-2-announcement">2.0 Announcement</a></li> -                  <li><a href="http://django-rest-framework.org/topics/2.2-announcement">2.2 Announcement</a></li> -                  <li><a href="http://django-rest-framework.org/topics/2.3-announcement">2.3 Announcement</a></li> -                  <li><a href="http://django-rest-framework.org/topics/release-notes">Release Notes</a></li> -                  <li><a href="http://django-rest-framework.org/topics/credits">Credits</a></li> +                  <li><a href="http://www.django-rest-framework.org/topics/documenting-your-api">Documenting your API</a></li> +                  <li><a href="http://www.django-rest-framework.org/topics/ajax-csrf-cors">AJAX, CSRF & CORS</a></li> +                  <li><a href="http://www.django-rest-framework.org/topics/browser-enhancements">Browser enhancements</a></li> +                  <li><a href="http://www.django-rest-framework.org/topics/browsable-api">The Browsable API</a></li> +                  <li><a href="http://www.django-rest-framework.org/topics/rest-hypermedia-hateoas">REST, Hypermedia & HATEOAS</a></li> +                  <li><a href="http://www.django-rest-framework.org/topics/rest-framework-2-announcement">2.0 Announcement</a></li> +                  <li><a href="http://www.django-rest-framework.org/topics/2.2-announcement">2.2 Announcement</a></li> +                  <li><a href="http://www.django-rest-framework.org/topics/2.3-announcement">2.3 Announcement</a></li> +                  <li><a href="http://www.django-rest-framework.org/topics/release-notes">Release Notes</a></li> +                  <li><a href="http://www.django-rest-framework.org/topics/credits">Credits</a></li>                  </ul>                </li>              </ul> @@ -160,7 +160,7 @@            <div id="main-content" class="span12">              <h1 id="404-page-not-found" style="text-align: center">404</h1>              <p style="text-align: center"><strong>Page not found</strong></p> -            <p style="text-align: center">Try the <a href="http://django-rest-framework.org/">homepage</a>, or <a href="#searchModal" data-toggle="modal">search the documentation</a>.</p> +            <p style="text-align: center">Try the <a href="http://www.django-rest-framework.org/">homepage</a>, or <a href="#searchModal" data-toggle="modal">search the documentation</a>.</p>            </div><!--/span-->          </div><!--/row-->        </div><!--/.fluid-container--> @@ -176,9 +176,9 @@      <!-- Le javascript      ================================================== -->      <!-- Placed at the end of the document so the pages load faster --> -    <script src="http://django-rest-framework.org/js/jquery-1.8.1-min.js"></script> -    <script src="http://django-rest-framework.org/js/prettify-1.0.js"></script> -    <script src="http://django-rest-framework.org/js/bootstrap-2.1.1-min.js"></script> +    <script src="http://www.django-rest-framework.org/js/jquery-1.8.1-min.js"></script> +    <script src="http://www.django-rest-framework.org/js/prettify-1.0.js"></script> +    <script src="http://www.django-rest-framework.org/js/bootstrap-2.1.1-min.js"></script>      <script>        //$('.side-nav').scrollspy()        var shiftWindow = function() { scrollBy(0, -50) }; diff --git a/docs/api-guide/authentication.md b/docs/api-guide/authentication.md index 53efc49a..88a7a011 100755 --- a/docs/api-guide/authentication.md +++ b/docs/api-guide/authentication.md @@ -93,7 +93,7 @@ Note that if deploying to [Apache using mod_wsgi][mod_wsgi_official], the author  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  +    # this can go in either server config, virtual host, directory or .htaccess      WSGIPassAuthorization On  --- @@ -117,7 +117,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: @@ -125,7 +125,7 @@ To use the `TokenAuthentication` scheme, include `rest_framework.authtoken` in y          ...          'rest_framework.authtoken'      ) -     +  Make sure to run `manage.py syncdb` after changing your settings. The `authtoken` database tables are managed by south (see [Schema migrations](#schema-migrations) below).  You'll also need to create tokens for your users. @@ -209,7 +209,7 @@ You can do so by inserting a `needed_by` attribute in your user migration:          needed_by = (              ('authtoken', '0001_initial'),          ) -         +          def forwards(self):              ... @@ -282,7 +282,7 @@ Note that the `namespace='oauth2'` argument is required.  Finally, sync your database.      python manage.py syncdb -    python manage.py migrate  +    python manage.py migrate  --- @@ -368,7 +368,7 @@ The following example will authenticate any incoming request as the user given b                  user = User.objects.get(username=username)              except User.DoesNotExist:                  raise exceptions.AuthenticationFailed('No such user') -             +              return (user, None)  --- @@ -389,6 +389,18 @@ The [Django OAuth Toolkit][django-oauth-toolkit] package provides OAuth 2.0 supp  The [Django OAuth2 Consumer][doac] library from [Rediker Software][rediker] is another package that provides [OAuth 2.0 support for REST framework][doac-rest-framework].  The package includes token scoping permissions on tokens, which allows finer-grained access to your API. +## JSON Web Token Authentication + +JSON Web Token is a fairly new standard which can be used for token-based authentication. Unlike the built-in TokenAuthentication scheme, JWT Authentication doesn't need to use a database to validate a token. [Blimp][blimp] maintains the [djangorestframework-jwt][djangorestframework-jwt] package which provides a JWT Authentication class as well as a mechanism for clients to obtain a JWT given the username and password. + +## Hawk HTTP Authentication + +The [HawkREST][hawkrest] library builds on the [Mohawk][mohawk] library to let you work with [Hawk][hawk] signed requests and responses in your API. [Hawk][hawk] lets two parties securely communicate with each other using messages signed by a shared key. It is based on [HTTP MAC access authentication][mac] (which was based on parts of [OAuth 1.0][oauth-1.0a]). + +## HTTP Signature Authentication + +HTTP Signature (currently a [IETF draft][http-signature-ietf-draft]) provides a way to achieve origin authentication and message integrity for HTTP messages. Similar to [Amazon's HTTP Signature scheme][amazon-http-signature], used by many of its services, it permits stateless, per-request authentication. [Elvio Toccalino][etoccalino] maintains the [djangorestframework-httpsignature][djangorestframework-httpsignature] package which provides an easy to use HTTP Signature Authentication mechanism. +  [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 @@ -413,3 +425,13 @@ The [Django OAuth2 Consumer][doac] library from [Rediker Software][rediker] is a  [doac]: https://github.com/Rediker-Software/doac  [rediker]: https://github.com/Rediker-Software  [doac-rest-framework]: https://github.com/Rediker-Software/doac/blob/master/docs/integrations.md# +[blimp]: https://github.com/GetBlimp +[djangorestframework-jwt]: https://github.com/GetBlimp/django-rest-framework-jwt +[etoccalino]: https://github.com/etoccalino/ +[djangorestframework-httpsignature]: https://github.com/etoccalino/django-rest-framework-httpsignature +[amazon-http-signature]: http://docs.aws.amazon.com/general/latest/gr/signature-version-4.html +[http-signature-ietf-draft]: https://datatracker.ietf.org/doc/draft-cavage-http-signatures/ +[hawkrest]: http://hawkrest.readthedocs.org/en/latest/ +[hawk]: https://github.com/hueniverse/hawk +[mohawk]: http://mohawk.readthedocs.org/en/latest/ +[mac]: http://tools.ietf.org/html/draft-hammer-oauth-v2-mac-token-05 diff --git a/docs/api-guide/exceptions.md b/docs/api-guide/exceptions.md index 221df679..66e18173 100644 --- a/docs/api-guide/exceptions.md +++ b/docs/api-guide/exceptions.md @@ -18,7 +18,7 @@ The handled exceptions are:  In each case, REST framework will return a response with an appropriate status code and content-type.  The body of the response will include any additional details regarding the nature of the error. -By default all error responses will include a key `details` in the body of the response, but other keys may also be included. +By default all error responses will include a key `detail` in the body of the response, but other keys may also be included.  For example, the following request: @@ -86,7 +86,7 @@ Note that the exception handler will only be called for responses generated by r  The **base class** for all exceptions raised inside REST framework. -To provide a custom exception, subclass `APIException` and set the `.status_code` and `.detail` properties on the class. +To provide a custom exception, subclass `APIException` and set the `.status_code` and `.default_detail` properties on the class.  For example, if your API relies on a third party service that may sometimes be unreachable, you might want to implement an exception for the "503 Service Unavailable" HTTP response code.  You could do this like so: @@ -94,7 +94,7 @@ For example, if your API relies on a third party service that may sometimes be u      class ServiceUnavailable(APIException):          status_code = 503 -        detail = 'Service temporarily unavailable, try again later.' +        default_detail = 'Service temporarily unavailable, try again later.'  ## ParseError diff --git a/docs/api-guide/fields.md b/docs/api-guide/fields.md index 83825350..883734a3 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] @@ -28,7 +28,13 @@ Defaults to the name of the field.  ### `read_only` -Set this to `True` to ensure that the field is used when serializing a representation, but is not used when updating an instance during deserialization. +Set this to `True` to ensure that the field is used when serializing a representation, but is not used when creating or updating an instance during deserialization. + +Defaults to `False` + +### `write_only` + +Set this to `True` to ensure that the field may be used when updating or creating an instance, but is not included when serializing the representation.  Defaults to `False` @@ -41,7 +47,7 @@ Defaults to `True`.  ### `default` -If set, this gives the default value that will be used for the field if no input value is supplied.  If not set the default behavior is to not populate the attribute at all.  +If set, this gives the default value that will be used for the field if no input value is supplied.  If not set the default behavior is to not populate the attribute at all.  May be set to a function or other callable, in which case the value will be evaluated each time it is used. @@ -86,7 +92,7 @@ For example, using the following model.          name = models.CharField(max_length=100)          created = models.DateTimeField(auto_now_add=True)          payment_expiry = models.DateTimeField() -         +          def has_expired(self):              return now() > self.payment_expiry @@ -96,8 +102,9 @@ A serializer definition that looked like this:      class AccountSerializer(serializers.HyperlinkedModelSerializer):          expired = serializers.Field(source='has_expired') -         +          class Meta: +            model = Account              fields = ('url', 'owner', 'name', 'expired')  Would produce output similar to: @@ -105,7 +112,7 @@ Would produce output similar to:      {          'url': 'http://example.com/api/accounts/3/',          'owner': 'http://example.com/api/users/12/', -        'name': 'FooCorp business account',  +        'name': 'FooCorp business account',          'expired': True      } @@ -119,7 +126,7 @@ A field that supports both read and write operations.  By itself `WritableField`  ## ModelField -A generic field that can be tied to any arbitrary model field.  The `ModelField` class delegates the task of serialization/deserialization to it's associated model field.  This field can be used to create serializer fields for custom model fields, without having to create a new custom serializer field. +A generic field that can be tied to any arbitrary model field.  The `ModelField` class delegates the task of serialization/deserialization to its associated model field.  This field can be used to create serializer fields for custom model fields, without having to create a new custom serializer field.  The `ModelField` class is generally intended for internal use, but can be used by your API if needed.  In order to properly instantiate a `ModelField`, it must be passed a field that is attached to an instantiated model.  For example: `ModelField(model_field=MyModel()._meta.get_field('custom_field'))` @@ -168,13 +175,13 @@ or `django.db.models.fields.TextField`.  Corresponds to `django.db.models.fields.URLField`.  Uses Django's `django.core.validators.URLValidator` for validation. -**Signature:** `CharField(max_length=200, min_length=None, allow_none=False)` +**Signature:** `URLField(max_length=200, min_length=None)`  ## SlugField  Corresponds to `django.db.models.fields.SlugField`. -**Signature:** `CharField(max_length=50, min_length=None, allow_none=False)` +**Signature:** `SlugField(max_length=50, min_length=None)`  ## ChoiceField @@ -218,7 +225,7 @@ In the case of JSON this means the default datetime representation uses the [ECM  **Signature:** `DateTimeField(format=None, input_formats=None)` -* `format` - A string representing the output format.  If not specified, this defaults to `None`, which indicates that Python `datetime` objects should be returned by `to_native`.  In this case the datetime encoding will be determined by the renderer.  +* `format` - A string representing the output format.  If not specified, this defaults to `None`, which indicates that Python `datetime` objects should be returned by `to_native`.  In this case the datetime encoding will be determined by the renderer.  * `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 specify 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.000000Z'`) @@ -278,7 +285,7 @@ Corresponds to `django.forms.fields.FileField`.  **Signature:** `FileField(max_length=None, allow_empty_file=False)`   - `max_length` designates the maximum length for the file name. -   +   - `allow_empty_file` designates if empty files are allowed.  ## ImageField @@ -302,7 +309,7 @@ Django's regular [FILE_UPLOAD_HANDLERS] are used for handling uploaded files.  If you want to create a custom field, you'll probably want to override either one or both of the `.to_native()` and `.from_native()` methods.  These two methods are used to convert between the initial datatype, and a primitive, serializable datatype.  Primitive datatypes may be any of a number, string, date/time/datetime or None.  They may also be any list or dictionary like object that only contains other primitive objects. -The `.to_native()` method is called to convert the initial datatype into a primitive, serializable datatype.  The `from_native()` method is called to restore a primitive datatype into it's initial representation. +The `.to_native()` method is called to convert the initial datatype into a primitive, serializable datatype.  The `from_native()` method is called to restore a primitive datatype into its initial representation.  ## Examples @@ -323,12 +330,12 @@ Let's look at an example of serializing a class that represents an RGB color val          """          def to_native(self, obj):              return "rgb(%d, %d, %d)" % (obj.red, obj.green, obj.blue) -       +          def from_native(self, data):              data = data.strip('rgb(').rstrip(')')              red, green, blue = [int(col) for col in data.split(',')]              return Color(red, green, blue) -             +  By default field values are treated as mapping to an attribute on the object.  If you need to customize how the field value is accessed and set you need to override `.field_to_native()` and/or `.field_from_native()`. @@ -341,8 +348,17 @@ As an example, let's create a field that can be used represent the class name of              """              return obj.__class__ +# Third party packages + +The following third party packages are also available. + +## DRF Compound Fields + +The [drf-compound-fields][drf-compound-fields] package provides "compound" serializer fields, such as lists of simple values, which can be described by other fields rather than serializers with the `many=True` option. Also provided are fields for typed dictionaries and values that can be either a specific type or a list of items of that type. +  [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  [ecma262]: http://ecma-international.org/ecma-262/5.1/#sec-15.9.1.15  [strftime]: http://docs.python.org/2/library/datetime.html#strftime-and-strptime-behavior  [iso8601]: http://www.w3.org/TR/NOTE-datetime +[drf-compound-fields]: http://drf-compound-fields.readthedocs.org diff --git a/docs/api-guide/filtering.md b/docs/api-guide/filtering.md index 0e02a2a7..6a8a267b 100644 --- a/docs/api-guide/filtering.md +++ b/docs/api-guide/filtering.md @@ -24,7 +24,7 @@ For example:      from myapp.serializers import PurchaseSerializer      from rest_framework import generics -    class PurchaseList(generics.ListAPIView) +    class PurchaseList(generics.ListAPIView):          serializer_class = PurchaseSerializer          def get_queryset(self): @@ -46,7 +46,7 @@ For example if your URL config contained an entry like this:  You could then write a view that returned a purchase queryset filtered by the username portion of the URL: -    class PurchaseList(generics.ListAPIView) +    class PurchaseList(generics.ListAPIView):          serializer_class = PurchaseSerializer          def get_queryset(self): @@ -63,7 +63,7 @@ A final example of filtering the initial queryset would be to determine the init  We can override `.get_queryset()` to deal with URLs such as `http://example.com/api/purchases?username=denvercoder9`, and filter the queryset only if the `username` parameter is included in the URL: -    class PurchaseList(generics.ListAPIView) +    class PurchaseList(generics.ListAPIView):          serializer_class = PurchaseSerializer          def get_queryset(self): @@ -264,13 +264,17 @@ For example:      search_fields = ('=username', '=email') +By default, the search parameter is named `'search`', but this may be overridden with the `SEARCH_PARAM` setting. +  For more details, see the [Django documentation][search-django-admin].  ---  ## OrderingFilter -The `OrderingFilter` class supports simple query parameter controlled ordering of results.  To specify the result order, set a query parameter named `'ordering'` to the required field name.  For example: +The `OrderingFilter` class supports simple query parameter controlled ordering of results.  By default, the query parameter is named `'ordering'`, but this may by overridden with the `ORDERING_PARAM` setting. + +For example, to order users by username:      http://example.com/api/users?ordering=username @@ -282,13 +286,37 @@ Multiple orderings may also be specified:      http://example.com/api/users?ordering=account,username +### Specifying which fields may be ordered against + +It's recommended that you explicitly specify which fields the API should allowing in the ordering filter.  You can do this by setting an `ordering_fields` attribute on the view, like so: + +    class UserListView(generics.ListAPIView): +        queryset = User.objects.all() +        serializer_class = UserSerializer +        filter_backends = (filters.OrderingFilter,) +        ordering_fields = ('username', 'email') + +This helps prevent unexpected data leakage, such as allowing users to order against a password hash field or other sensitive data. + +If you *don't* specify an `ordering_fields` attribute on the view, the filter class will default to allowing the user to filter on any readable fields on the serializer specified by the `serializer_class` attribute. + +If you are confident that the queryset being used by the view doesn't contain any sensitive data, you can also explicitly specify that a view should allow ordering on *any* model field or queryset aggregate, by using the special value `'__all__'`. + +    class BookingsListView(generics.ListAPIView): +        queryset = Booking.objects.all() +        serializer_class = BookingSerializer +        filter_backends = (filters.OrderingFilter,) +        ordering_fields = '__all__' + +### Specifying a default ordering +  If an `ordering` attribute is set on the view, this will be used as the default ordering.  Typically you'd instead control this by setting `order_by` on the initial queryset, but using the `ordering` parameter on the view allows you to specify the ordering in a way that it can then be passed automatically as context to a rendered template.  This makes it possible to automatically render column headers differently if they are being used to order the results.      class UserListView(generics.ListAPIView):          queryset = User.objects.all() -        serializer = UserSerializer +        serializer_class = UserSerializer          filter_backends = (filters.OrderingFilter,)          ordering = ('username',)  diff --git a/docs/api-guide/generic-views.md b/docs/api-guide/generic-views.md index 83c3e45f..fb927ea8 100755 --- a/docs/api-guide/generic-views.md +++ b/docs/api-guide/generic-views.md @@ -119,7 +119,7 @@ For example:          self.check_object_permissions(self.request, obj)          return obj -Note that if your API doesn't include any object level permissions, you may optionally exclude the ``self.check_object_permissions, and simply return the object from the `get_object_or_404` lookup. +Note that if your API doesn't include any object level permissions, you may optionally exclude the `self.check_object_permissions`, and simply return the object from the `get_object_or_404` lookup.  #### `get_filter_backends(self)` @@ -362,11 +362,20 @@ If you are using a mixin across multiple views, you can take this a step further  Using custom base classes is a good option if you have custom behavior that consistently needs to be repeated across a large number of views throughout your project. -[cite]: https://docs.djangoproject.com/en/dev/ref/class-based-views/#base-vs-generic-views +# Third party packages + +The following third party packages provide additional generic view implementations. + +## Django REST Framework bulk +The [django-rest-framework-bulk package][django-rest-framework-bulk] implements generic view mixins as well as some common concrete generic views to allow to apply bulk operations via API requests. + + +[cite]: https://docs.djangoproject.com/en/dev/ref/class-based-views/#base-vs-generic-views  [GenericAPIView]: #genericapiview  [ListModelMixin]: #listmodelmixin  [CreateModelMixin]: #createmodelmixin  [RetrieveModelMixin]: #retrievemodelmixin  [UpdateModelMixin]: #updatemodelmixin  [DestroyModelMixin]: #destroymodelmixin +[django-rest-framework-bulk]: https://github.com/miki725/django-rest-framework-bulk diff --git a/docs/api-guide/pagination.md b/docs/api-guide/pagination.md index 0829589f..efc4ae7f 100644 --- a/docs/api-guide/pagination.md +++ b/docs/api-guide/pagination.md @@ -147,4 +147,14 @@ Alternatively, to set your custom pagination serializer on a per-view basis, use          pagination_serializer_class = CustomPaginationSerializer          paginate_by = 10 +# Third party packages + +The following third party packages are also available. + +## DRF-extensions + +The [`DRF-extensions` package][drf-extensions] includes a [`PaginateByMaxMixin` mixin class][paginate-by-max-mixin] that allows your API clients to specify `?page_size=max` to obtain the maximum allowed page size. +  [cite]: https://docs.djangoproject.com/en/dev/topics/pagination/ +[drf-extensions]: http://chibisov.github.io/drf-extensions/docs/ +[paginate-by-max-mixin]: http://chibisov.github.io/drf-extensions/docs/#paginatebymaxmixin
\ No newline at end of file diff --git a/docs/api-guide/relations.md b/docs/api-guide/relations.md index 1b089c54..cc4f5585 100644 --- a/docs/api-guide/relations.md +++ b/docs/api-guide/relations.md @@ -134,7 +134,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**. +* `view_name` - The view name that should be used as the target of the relationship.  If you're using [the standard router classes][routers] this wil be a string with the format `<modelname>-detail`. **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`. @@ -202,7 +202,7 @@ This field is always read-only.  **Arguments**: -* `view_name` - The view name that should be used as the target of the relationship.  **required**. +* `view_name` - The view name that should be used as the target of the relationship.  If you're using [the standard router classes][routers] this wil be a string with the format `<model_name>-detail`.  **required**.  * `lookup_field` - The field on the target that should be used for the lookup.  Should correspond to a URL keyword argument on the referenced view.  Default is `'pk'`.  * `format` - If using format suffixes, hyperlinked fields will use the same format suffix for the target unless overridden by using the `format` argument. @@ -454,6 +454,7 @@ The [drf-nested-routers package][drf-nested-routers] provides routers and relati  [cite]: http://lwn.net/Articles/193245/  [reverse-relationships]: https://docs.djangoproject.com/en/dev/topics/db/queries/#following-relationships-backward +[routers]: http://www.django-rest-framework.org/api-guide/routers#defaultrouter  [generic-relations]: https://docs.djangoproject.com/en/dev/ref/contrib/contenttypes/#id1  [2.2-announcement]: ../topics/2.2-announcement.md  [drf-nested-routers]: https://github.com/alanjds/drf-nested-routers diff --git a/docs/api-guide/routers.md b/docs/api-guide/routers.md index 249e99a4..819cf980 100644 --- a/docs/api-guide/routers.md +++ b/docs/api-guide/routers.md @@ -37,7 +37,19 @@ The example above would generate the following URL patterns:  * URL pattern: `^accounts/$`  Name: `'account-list'`  * URL pattern: `^accounts/{pk}/$`  Name: `'account-detail'` -### Registering additional routes +--- + +**Note**: The `base_name` argument is used to specify the initial part of the view name pattern.  In the example above, that's the `user` or `account` part. + +Typically you won't *need* to specify the `base-name` argument, but if you have a viewset where you've defined a custom `get_queryset` method, then the viewset may not have any `.model` or `.queryset` attribute set.  If you try to register that viewset you'll see an error like this: + +    'base_name' argument not specified, and could not automatically determine the name from the viewset, as it does not have a '.model' or '.queryset' attribute. + +This means you'll need to explicitly set the `base_name` argument when registering the viewset, as it could not be automatically determined from the model name. + +--- + +### Extra link and actions  Any methods on the viewset decorated with `@detail_route` or `@list_route` will also be routed.  For example, given a method like this on the `UserViewSet` class: diff --git a/docs/api-guide/serializers.md b/docs/api-guide/serializers.md index 6fc25f57..7ee060af 100644 --- a/docs/api-guide/serializers.md +++ b/docs/api-guide/serializers.md @@ -103,11 +103,11 @@ Deserialization is similar.  First we parse a stream into Python native datatype  When deserializing data, we can either create a new instance, or update an existing instance.      serializer = CommentSerializer(data=data)           # Create new instance -    serializer = CommentSerializer(comment, data=data)  # Update `instance` +    serializer = CommentSerializer(comment, data=data)  # Update `comment`  By default, serializers must be passed values for all required fields or they will throw validation errors.  You can use the `partial` argument in order to allow partial updates. -    serializer = CommentSerializer(comment, data={'content': u'foo bar'}, partial=True)  # Update `instance` with partial data +    serializer = CommentSerializer(comment, data={'content': u'foo bar'}, partial=True)  # Update `comment` with partial data  ## Validation @@ -161,7 +161,7 @@ To do any other validation that requires access to multiple fields, add a method              """              Check that the start is before the stop.              """ -            if attrs['start'] < attrs['finish']: +            if attrs['start'] > attrs['finish']:                  raise serializers.ValidationError("finish must occur after start")              return attrs @@ -208,7 +208,7 @@ Similarly if a nested representation should be a list of items, you should pass  Validation of nested objects will work the same as before.  Errors with nested objects will be nested under the field name of the nested object. -    serializer = CommentSerializer(comment, data={'user': {'email': 'foobar', 'username': 'doe'}, 'content': 'baz'}) +    serializer = CommentSerializer(data={'user': {'email': 'foobar', 'username': 'doe'}, 'content': 'baz'})      serializer.is_valid()      # False      serializer.errors @@ -373,6 +373,25 @@ You may wish to specify multiple fields as read-only.  Instead of adding each fi  Model fields which have `editable=False` set, and `AutoField` fields will be set to read-only by default, and do not need to be added to the `read_only_fields` option.  +## Specifying which fields should be write-only  + +You may wish to specify multiple fields as write-only.  Instead of adding each field explicitly with the `write_only=True` attribute, you may use the `write_only_fields` Meta option, like so: + +    class CreateUserSerializer(serializers.ModelSerializer): +        class Meta: +            model = User +            fields = ('email', 'username', 'password') +            write_only_fields = ('password',)  # Note: Password field is write-only + +        def restore_object(self, attrs, instance=None): +            """ +            Instantiate a new User instance. +            """ +            assert instance is None, 'Cannot update users with CreateUserSerializer'                                 +            user = User(email=attrs['email'], username=attrs['username']) +            user.set_password(attrs['password']) +            return user +   ## 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. @@ -445,6 +464,29 @@ For more specific requirements such as specifying a different lookup for each fi              model = Account              fields = ('url', 'account_name', 'users', 'created') +## Overiding the URL field behavior + +The name of the URL field defaults to 'url'.  You can override this globally, by using the `URL_FIELD_NAME` setting. + +You can also override this on a per-serializer basis by using the `url_field_name` option on the serializer, like so: + +    class AccountSerializer(serializers.HyperlinkedModelSerializer): +        class Meta: +            model = Account +            fields = ('account_url', 'account_name', 'users', 'created') +            url_field_name = 'account_url' + +**Note**: The generic view implementations normally generate a `Location` header in response to successful `POST` requests.  Serializers using `url_field_name` option will not have this header automatically included by the view.  If you need to do so you will ned to also override the view's `get_success_headers()` method. + +You can also overide the URL field's view name and lookup field without overriding the field explicitly, by using the `view_name` and `lookup_field` options, like so: + +    class AccountSerializer(serializers.HyperlinkedModelSerializer): +        class Meta: +            model = Account +            fields = ('account_url', 'account_name', 'users', 'created') +            view_name = 'account_detail' +            lookup_field='account_name' +  ---  # Advanced serializer usage diff --git a/docs/api-guide/settings.md b/docs/api-guide/settings.md index d8c878ff..8bde4d87 100644 --- a/docs/api-guide/settings.md +++ b/docs/api-guide/settings.md @@ -158,6 +158,18 @@ A client request like the following would return a paginated list of up to 100 i  Default: `None` +### SEARCH_PARAM + +The name of a query paramater, which can be used to specify the search term used by `SearchFilter`. + +Default: `search` + +#### ORDERING_PARAM + +The name of a query paramater, which can be used to specify the ordering of results returned by `OrderingFilter`. + +Default: `ordering` +  ---  ## Authentication settings @@ -353,6 +365,12 @@ This should be a function with the following signature:  Default: `'rest_framework.views.exception_handler'` +#### URL_FIELD_NAME + +A string representing the key that should be used for the URL fields generated by `HyperlinkedModelSerializer`. + +Default: `'url'` +  #### FORMAT_SUFFIX_KWARG  The name of a parameter in the URL conf that may be used to provide a format suffix. diff --git a/docs/api-guide/testing.md b/docs/api-guide/testing.md index 4a8a9168..72c33961 100644 --- a/docs/api-guide/testing.md +++ b/docs/api-guide/testing.md @@ -218,12 +218,12 @@ You can use any of REST framework's test case classes as you would for the regul  When checking the validity of test responses it's often more convenient to inspect the data that the response was created with, rather than inspecting the fully rendered response. -For example, it's easier to inspect `request.data`: +For example, it's easier to inspect `response.data`:      response = self.client.get('/users/4/')      self.assertEqual(response.data, {'id': 4, 'username': 'lauren'}) -Instead of inspecting the result of parsing `request.content`: +Instead of inspecting the result of parsing `response.content`:      response = self.client.get('/users/4/')      self.assertEqual(json.loads(response.content), {'id': 4, 'username': 'lauren'}) diff --git a/docs/api-guide/throttling.md b/docs/api-guide/throttling.md index bedecb36..d223f9b3 100644 --- a/docs/api-guide/throttling.md +++ b/docs/api-guide/throttling.md @@ -160,7 +160,7 @@ For example, given the following views...      REST_FRAMEWORK = {          'DEFAULT_THROTTLE_CLASSES': ( -            'rest_framework.throttling.ScopedRateThrottle' +            'rest_framework.throttling.ScopedRateThrottle',          ),          'DEFAULT_THROTTLE_RATES': {              'contacts': '1000/day', diff --git a/docs/api-guide/viewsets.md b/docs/api-guide/viewsets.md index dfd9d22a..161fd2a9 100644 --- a/docs/api-guide/viewsets.md +++ b/docs/api-guide/viewsets.md @@ -233,7 +233,7 @@ To create a base viewset class that provides `create`, `list` and `retrieve` ope                                      mixins.RetrieveModelMixin,                                      viewsets.GenericViewSet):          """ -        A viewset that provides `retrieve`, `update`, and `list` actions. +        A viewset that provides `retrieve`, `create`, and `list` actions.          To use it, override the class and set the `.queryset` and          `.serializer_class` attributes. diff --git a/docs/img/logo.png b/docs/img/logo.pngBinary files differ new file mode 100644 index 00000000..73de34f4 --- /dev/null +++ b/docs/img/logo.png diff --git a/docs/index.md b/docs/index.md index 04804fa7..2a4ad885 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,15 +1,30 @@ -<p class="badges"> +<p class="badges" height=20px>  <iframe src="http://ghbtns.com/github-btn.html?user=tomchristie&repo=django-rest-framework&type=watch&count=true" class="github-star-button" allowtransparency="true" frameborder="0" scrolling="0" width="110px" height="20px"></iframe> -<a href="https://twitter.com/share" class="twitter-share-button" data-url="django-rest-framework.org" data-text="Checking out the totally awesome Django REST framework! http://django-rest-framework.org" data-count="none"></a> +<a href="https://twitter.com/share" class="twitter-share-button" data-url="django-rest-framework.org" data-text="Checking out the totally awesome Django REST framework! http://www.django-rest-framework.org" data-count="none"></a>  <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="http://platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>  <img src="https://secure.travis-ci.org/tomchristie/django-rest-framework.png?branch=master" class="travis-build-image">  </p> -# Django REST framework +--- + +<p> +<h1 style="position: absolute; +    width: 1px; +    height: 1px; +    padding: 0; +    margin: -1px; +    overflow: hidden; +    clip: rect(0,0,0,0); +    border: 0;">Django REST Framework</h1> -**Awesome web-browsable Web APIs.** +<img alt="Django REST Framework" title="Logo by Jake 'Sid' Smith" src="img/logo.png" width="600px" style="display: block; margin: 0 auto 0 auto"> +</p> + +<!-- +# Django REST framework +-->  Django REST framework is a powerful and flexible toolkit that makes it easy to build Web APIs. @@ -20,13 +35,16 @@ Some reasons you might want to use REST framework:  * [Serialization][serializers] that supports both [ORM][modelserializer-section] and [non-ORM][serializer-section] data sources.  * Customizable all the way down - just use [regular function-based views][functionview-section] if you don't need the [more][generic-views] [powerful][viewsets] [features][routers].  * [Extensive documentation][index], and [great community support][group]. +* Used and trusted by large companies such as [Mozilla][mozilla] and [Eventbrite][eventbrite]. -There is a live example API for testing purposes, [available here][sandbox]. - -**Below**: *Screenshot from the browsable API* +---  ![Screenshot][image] +**Above**: *Screenshot from the browsable API* + +---- +  ## Requirements  REST framework requires the following: @@ -62,7 +80,7 @@ Add `'rest_framework'` to your `INSTALLED_APPS` setting.      INSTALLED_APPS = (          ... -        'rest_framework',         +        'rest_framework',      )  If you're intending to use the browsable API you'll probably also want to add REST framework's login and logout views.  Add the following to your root `urls.py` file. @@ -111,7 +129,7 @@ Here's our project's root `urls.py` module:      class GroupViewSet(viewsets.ModelViewSet):          model = Group -     +      # Routers provide an easy way of automatically determining the URL conf.      router = routers.DefaultRouter()      router.register(r'users', UserViewSet) @@ -140,6 +158,8 @@ The tutorial will walk you through the building blocks that make up REST framewo  * [5 - Relationships & hyperlinked APIs][tut-5]  * [6 - Viewsets & routers][tut-6] +There is a live example API of the finished tutorial API for testing purposes, [available here][sandbox]. +  ## API Guide  The API guide is your complete reference manual to all the functionality provided by REST framework. @@ -196,7 +216,7 @@ 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`:  +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 @@ -219,32 +239,33 @@ Send a description of the issue via email to [rest-framework-security@googlegrou  ## License -Copyright (c) 2011-2013, Tom Christie +Copyright (c) 2011-2014, Tom Christie  All rights reserved. -Redistribution and use in source and binary forms, with or without  +Redistribution and use in source and binary forms, with or without  modification, are permitted provided that the following conditions are met: -Redistributions of source code must retain the above copyright notice, this  +Redistributions of source code must retain the above copyright notice, this  list of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this  -list of conditions and the following disclaimer in the documentation and/or  +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or  other materials provided with the distribution. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND  -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED  -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE  -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE  -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL  -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR  -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER  -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,  -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE  +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  [travis]: http://travis-ci.org/tomchristie/django-rest-framework?branch=master  [travis-build-image]: https://secure.travis-ci.org/tomchristie/django-rest-framework.png?branch=master -[urlobject]: https://github.com/zacharyvoase/urlobject +[mozilla]: http://www.mozilla.org/en-US/about/ +[eventbrite]: https://www.eventbrite.co.uk/about/  [markdown]: http://pypi.python.org/pypi/Markdown/  [yaml]: http://pypi.python.org/pypi/PyYAML  [defusedxml]: https://pypi.python.org/pypi/defusedxml diff --git a/docs/template.html b/docs/template.html index c065237a..a397d067 100644 --- a/docs/template.html +++ b/docs/template.html @@ -170,31 +170,12 @@                <ul class="nav nav-list side-nav well sidebar-nav-fixed">                  {{ toc }}                <div> -              <hr> - -<p><strong>The team behind REST framework is launching a new API service.</strong></p> - -<p>If you want to be first in line when we start issuing invitations, please sign up here:</p> - -<!-- Begin MailChimp Signup Form --> -<link href="//cdn-images.mailchimp.com/embedcode/slim-081711.css" rel="stylesheet" type="text/css"> -<style type="text/css"> -    #mc_embed_signup{background:#fff; clear:left; font:14px Helvetica,Arial,sans-serif; } -    /* Add your own MailChimp form style overrides in your site stylesheet or in this style block. -       We recommend moving this block and the preceding CSS link to the HEAD of your HTML file. */ -</style> -<div id="mc_embed_signup" style="background: rgb(245, 245, 245)"> -<form action="http://dabapps.us1.list-manage1.com/subscribe/post?u=cf73a9994eb5b8d8d461b5dfb&id=cb6af8e8bd" method="post" id="mc-embedded-subscribe-form" name="mc-embedded-subscribe-form" class="validate" target="_blank" novalidate> -<!--     <label for="mce-EMAIL">Keep me posted!</label> - -->    <input style="width: 90%" type="email" value="" name="EMAIL" class="email" id="mce-EMAIL" placeholder="email address" required> -    <div class="clear"><input class="btn btn-success" type="submit" value="Yes, keep me posted!" name="subscribe" id="mc-embedded-subscribe" class="button"></div> -</form> -</div> -</style></div> -              </ul> +{{ ad_block }} + +</div> +</ul> -<!--End mc_embed_signup-->              </div>            </div> diff --git a/docs/topics/2.2-announcement.md b/docs/topics/2.2-announcement.md index 0f980e1c..a997c782 100644 --- a/docs/topics/2.2-announcement.md +++ b/docs/topics/2.2-announcement.md @@ -151,7 +151,7 @@ From version 2.2 onwards, serializers with hyperlinked relationships *always* re  [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 +[credits]: http://www.django-rest-framework.org/topics/credits  [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/ diff --git a/docs/topics/contributing.md b/docs/topics/contributing.md index 30d292f8..18a05050 100644 --- a/docs/topics/contributing.md +++ b/docs/topics/contributing.md @@ -14,7 +14,7 @@ If you use REST framework, we'd love you to be vocal about your experiences with  Other really great ways you can help move the community forward include helping answer questions on the [discussion group][google-group], or setting up an [email alert on StackOverflow][so-filter] so that you get notified of any new questions with the `django-rest-framework` tag. -When answering questions make sure to help future contributors find their way around by hyperlinking wherever possible to related threads and tickets, and include backlinks from those items if relevant.  +When answering questions make sure to help future contributors find their way around by hyperlinking wherever possible to related threads and tickets, and include backlinks from those items if relevant.  ## Code of conduct @@ -38,7 +38,7 @@ Some tips on good issue reporting:  ## Triaging issues -Getting involved in triaging incoming issues is a good way to start contributing.  Every single ticket that comes into the ticket tracker needs to be reviewed in order to determine what the next steps should be.  Anyone can help out with this, you just need to be willing to  +Getting involved in triaging incoming issues is a good way to start contributing.  Every single ticket that comes into the ticket tracker needs to be reviewed in order to determine what the next steps should be.  Anyone can help out with this, you just need to be willing to  * Read through the ticket - does it make sense, is it missing any context that would help explain it better?  * Is the ticket reported in the correct place, would it be better suited as a discussion on the discussion group? @@ -60,14 +60,14 @@ To run the tests, clone the repository, and then:      # Setup the virtual environment      virtualenv env -    env/bin/activate +    source env/bin/activate      pip install -r requirements.txt      pip install -r optionals.txt      # Run the tests      rest_framework/runtests/runtests.py -You can also use the excellent `[tox][tox]` testing tool to run the tests against all supported versions of Python and Django.  Install `tox` globally, and then simply run: +You can also use the excellent [tox][tox] testing tool to run the tests against all supported versions of Python and Django.  Install `tox` globally, and then simply run:      tox @@ -130,8 +130,8 @@ There are a couple of conventions you should follow when working on the document  Headers should use the hash style.  For example:      ### Some important topic -     -The underline style should not be used.  **Don't do this:**  + +The underline style should not be used.  **Don't do this:**      Some important topic      ==================== @@ -141,9 +141,9 @@ The underline style should not be used.  **Don't do this:**  Links should always use the reference style, with the referenced hyperlinks kept at the end of the document.      Here is a link to [some other thing][other-thing]. -     +      More text... -     +      [other-thing]: http://example.com/other/thing  This style helps keep the documentation source consistent and readable. @@ -159,9 +159,9 @@ Linking in this style means you'll be able to click the hyperlink in your markdo  If you want to draw attention to a note or warning, use a pair of enclosing lines, like so:      --- -     +      **Note:** A useful documentation note. -     +      ---  # Third party packages diff --git a/docs/topics/credits.md b/docs/topics/credits.md index d4c00bc4..5f0dc752 100644 --- a/docs/topics/credits.md +++ b/docs/topics/credits.md @@ -182,6 +182,7 @@ The following people have helped make REST framework great.  * Ian Foote - [ian-foote]  * Chuck Harmston - [chuckharmston]  * Philip Forget - [philipforget] +* Artem Mezhenin - [amezhenin]  Many thanks to everyone who's contributed to the project. @@ -400,3 +401,4 @@ You can also contact [@_tomchristie][twitter] directly on twitter.  [ian-foote]: https://github.com/ian-foote  [chuckharmston]: https://github.com/chuckharmston  [philipforget]: https://github.com/philipforget +[amezhenin]: https://github.com/amezhenin diff --git a/docs/topics/release-notes.md b/docs/topics/release-notes.md index da17aa74..37addc8d 100644 --- a/docs/topics/release-notes.md +++ b/docs/topics/release-notes.md @@ -38,8 +38,6 @@ You can determine your currently installed version using `pip freeze`:  --- -## 2.3.x series -  ### 2.4.0  * `@detail_route` and `@list_route` decorators replace `@action` and `@link`. @@ -50,12 +48,40 @@ You can determine your currently installed version using `pip freeze`:  * Added `cache` attribute to throttles to allow overriding of default cache.  * Bugfix: `?page_size=0` query parameter now falls back to default page size for view, instead of always turning pagination off. -### Master +## 2.3.x series + +### 2.3.13 +## 2.3.x series + + +**Date**: 6th March 2014 + +* Django 1.7 Support. +* Fix `default` argument when used with serializer relation fields. +* Display the media type of the content that is being displayed in the browsable API, rather than 'text/html'. +* Bugfix for `urlize` template failure when URL regex is matched, but value does not `urlparse`. +* Use `urandom` for token generation. +* Only use `Vary: Accept` when more than one renderer exists. + +### 2.3.12 + +**Date**: 15th January 2014 + +* **Security fix**: `OrderingField` now only allows ordering on readable serializer fields, or on fields explicitly specified using `ordering_fields`. This prevents users being able to order by fields that are not visible in the API, and exploiting the ordering of sensitive data such as password hashes. +* Bugfix: `write_only = True` fields now display in the browsable API. + +### 2.3.11 + +**Date**: 14th January 2014 + +* Added `write_only` serializer field argument. +* Added `write_only_fields` option to `ModelSerializer` classes.  * JSON renderer now deals with objects that implement a dict-like interface.  * Fix compatiblity with newer versions of `django-oauth-plus`.  * Bugfix: Refine behavior that calls model manager `all()` across nested serializer relationships, preventing erronous behavior with some non-ORM objects, and preventing unneccessary queryset re-evaluations.  * Bugfix: Allow defaults on BooleanFields to be properly honored when values are not supplied. +* Bugfix: Prevent double-escaping of non-latin1 URL query params when appending `format=json` params.  ### 2.3.10 @@ -74,7 +100,6 @@ You can determine your currently installed version using `pip freeze`:  * Fix Django 1.6 exception API compatibility issue caused by `ValidationError`.  * Include errors in HTML forms in browsable API. ->>>>>>> master  * Added JSON renderer support for numpy scalars.  * Added `transform_<fieldname>` hooks on serializers for easily modifying field output.  * Added `get_context` hook in `BrowsableAPIRenderer`. @@ -100,15 +125,15 @@ You can determine your currently installed version using `pip freeze`:  * Bugfix: `client.force_authenticate(None)` should also clear session info if it exists.  * Bugfix: Client sending empty string instead of file now clears `FileField`.  * Bugfix: Empty values on ChoiceFields with `required=False` now consistently return `None`. -* Bugfix: Clients setting `page=0` now simply returns the default page size, instead of disabling pagination. [*] +* Bugfix: Clients setting `page_size=0` now simply returns the default page size, instead of disabling pagination. [*]  --- -[*] Note that the change in `page=0` behaviour fixes what is considered to be a bug in how clients can effect the pagination size.  However if you were relying on this behavior you will need to add the following mixin to your list views in order to preserve the existing behavior. +[*] Note that the change in `page_size=0` behaviour fixes what is considered to be a bug in how clients can effect the pagination size.  However if you were relying on this behavior you will need to add the following mixin to your list views in order to preserve the existing behavior.      class DisablePaginationMixin(object):          def get_paginate_by(self, queryset=None): -            if self.request.QUERY_PARAMS['self.paginate_by_param'] == '0': +            if self.request.QUERY_PARAMS[self.paginate_by_param] == '0':                  return None              return super(DisablePaginationMixin, self).get_paginate_by(queryset) diff --git a/docs/tutorial/1-serialization.md b/docs/tutorial/1-serialization.md index 2298df59..979c4a3e 100644 --- a/docs/tutorial/1-serialization.md +++ b/docs/tutorial/1-serialization.md @@ -17,9 +17,8 @@ The tutorial is fairly in-depth, so you should probably get a cookie and a cup o  Before we do anything else we'll create a new virtual environment, using [virtualenv].  This will make sure our package configuration is kept nicely isolated from any other projects we're working on.      :::bash -    mkdir ~/env -    virtualenv ~/env/tutorial -    source ~/env/tutorial/bin/activate +    virtualenv env +    source env/bin/activate  Now that we're inside a virtualenv environment, we can install our package requirements. diff --git a/docs/tutorial/4-authentication-and-permissions.md b/docs/tutorial/4-authentication-and-permissions.md index bdc6b579..432371f3 100644 --- a/docs/tutorial/4-authentication-and-permissions.md +++ b/docs/tutorial/4-authentication-and-permissions.md @@ -129,7 +129,7 @@ Then, add the following property to **both** the `SnippetList` and `SnippetDetai  If you open a browser and navigate to the browsable 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. -We can add a login view for use with the browsable API, by editing our URLconf once more. +We can add a login view for use with the browsable API, by editing the URLconf in our project-level urls.py file.  Add the following import at the top of the file: | 
