diff --git a/.travis.yml b/.travis.yml index f89e77531..7266df2d5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,13 +14,16 @@ matrix: - { python: "3.6", env: DJANGO=2.0 } - { python: "3.6", env: DJANGO=2.1 } - { python: "3.6", env: DJANGO=2.2 } + - { python: "3.6", env: DJANGO=3.0 } - { python: "3.6", env: DJANGO=master } - { python: "3.7", env: DJANGO=2.0 } - { python: "3.7", env: DJANGO=2.1 } - { python: "3.7", env: DJANGO=2.2 } + - { python: "3.7", env: DJANGO=3.0 } - { python: "3.7", env: DJANGO=master } + - { python: "3.8", env: DJANGO=3.0 } - { python: "3.8", env: DJANGO=master } - { python: "3.8", env: TOXENV=base } diff --git a/MANIFEST.in b/MANIFEST.in index 6f7cb8f13..262e3dc91 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,5 +1,6 @@ include README.md include LICENSE.md +recursive-include tests/* * recursive-include rest_framework/static *.js *.css *.png *.ico *.eot *.svg *.ttf *.woff *.woff2 recursive-include rest_framework/templates *.html schema.js recursive-include rest_framework/locale *.mo diff --git a/README.md b/README.md index 8774bc854..9591bdc17 100644 --- a/README.md +++ b/README.md @@ -54,8 +54,8 @@ There is a live example API for testing purposes, [available here][sandbox]. # Requirements -* Python (3.5, 3.6, 3.7) -* Django (1.11, 2.0, 2.1, 2.2) +* Python (3.5, 3.6, 3.7, 3.8) +* Django (1.11, 2.0, 2.1, 2.2, 3.0) We **highly recommend** and only officially support the latest patch release of each Python and Django series. diff --git a/docs/api-guide/fields.md b/docs/api-guide/fields.md index 29cb5aec9..65c83b78e 100644 --- a/docs/api-guide/fields.md +++ b/docs/api-guide/fields.md @@ -50,7 +50,19 @@ If set, this gives the default value that will be used for the field if no input The `default` is not applied during partial update operations. In the partial update case only fields that are provided in the incoming data will have a validated value returned. -May be set to a function or other callable, in which case the value will be evaluated each time it is used. When called, it will receive no arguments. If the callable has a `set_context` method, that will be called each time before getting the value with the field instance as only argument. This works the same way as for [validators](validators.md#using-set_context). +May be set to a function or other callable, in which case the value will be evaluated each time it is used. When called, it will receive no arguments. If the callable has a `requires_context = True` attribute, then the serializer field will be passed as an argument. + +For example: + + class CurrentUserDefault: + """ + May be applied as a `default=...` value on a serializer field. + Returns the current user. + """ + requires_context = True + + def __call__(self, serializer_field): + return serializer_field.context['request'].user When serializing the instance, default will be used if the object attribute or dictionary key is not present in the instance. @@ -585,8 +597,6 @@ The `.to_representation()` method is called to convert the initial datatype into The `to_internal_value()` method is called to restore a primitive datatype into its internal python representation. This method should raise a `serializers.ValidationError` if the data is invalid. -Note that the `WritableField` class that was present in version 2.x no longer exists. You should subclass `Field` and override `to_internal_value()` if the field supports data input. - ## Examples ### A Basic Custom Field diff --git a/docs/api-guide/filtering.md b/docs/api-guide/filtering.md index 1bdb6c52b..bad57b441 100644 --- a/docs/api-guide/filtering.md +++ b/docs/api-guide/filtering.md @@ -212,7 +212,7 @@ The search behavior may be restricted by prepending various characters to the `s * '^' Starts-with search. * '=' Exact matches. -* '@' Full-text search. (Currently only supported Django's MySQL backend.) +* '@' Full-text search. (Currently only supported Django's [PostgreSQL backend](https://docs.djangoproject.com/en/dev/ref/contrib/postgres/search/).) * '$' Regex search. For example: diff --git a/docs/api-guide/generic-views.md b/docs/api-guide/generic-views.md index a2f19ff2e..a256eb2d9 100644 --- a/docs/api-guide/generic-views.md +++ b/docs/api-guide/generic-views.md @@ -175,8 +175,6 @@ You can also use these hooks to provide additional validation, by raising a `Val raise ValidationError('You have already signed up') serializer.save(user=self.request.user) -**Note**: These methods replace the old-style version 2.x `pre_save`, `post_save`, `pre_delete` and `post_delete` methods, which are no longer available. - **Other methods**: You won't typically need to override the following methods, although you might need to call into them if you're writing custom views using `GenericAPIView`. diff --git a/docs/api-guide/relations.md b/docs/api-guide/relations.md index 14f197b21..ef6efec5e 100644 --- a/docs/api-guide/relations.md +++ b/docs/api-guide/relations.md @@ -245,7 +245,9 @@ This field is always read-only. # Nested relationships -Nested relationships can be expressed by using serializers as fields. +As opposed to previously discussed _references_ to another entity, the referred entity can instead also be embedded or _nested_ +in the representation of the object that refers to it. +Such 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. diff --git a/docs/api-guide/validators.md b/docs/api-guide/validators.md index 49685838a..009cd2468 100644 --- a/docs/api-guide/validators.md +++ b/docs/api-guide/validators.md @@ -291,13 +291,17 @@ To write a class-based validator, use the `__call__` method. Class-based validat message = 'This field must be a multiple of %d.' % self.base raise serializers.ValidationError(message) -#### Using `set_context()` +#### Accessing the context -In some advanced cases you might want a validator to be passed the serializer field it is being used with as additional context. You can do so by declaring a `set_context` method on a class-based validator. +In some advanced cases you might want a validator to be passed the serializer +field it is being used with as additional context. You can do so by setting +a `requires_context = True` attribute on the validator. The `__call__` method +will then be called with the `serializer_field` +or `serializer` as an additional argument. - def set_context(self, serializer_field): - # Determine if this is an update or a create operation. - # In `__call__` we can then use that information to modify the validation behavior. - self.is_update = serializer_field.parent.instance is not None + requires_context = True + + def __call__(self, value, serializer_field): + ... [cite]: https://docs.djangoproject.com/en/stable/ref/validators/ diff --git a/docs/community/3.10-announcement.md b/docs/community/3.10-announcement.md index 578e900dc..19748aa40 100644 --- a/docs/community/3.10-announcement.md +++ b/docs/community/3.10-announcement.md @@ -144,4 +144,4 @@ continued development by **[signing up for a paid plan][funding]**. [legacy-core-api-docs]:https://github.com/encode/django-rest-framework/blob/master/docs/coreapi/index.md [sponsors]: https://fund.django-rest-framework.org/topics/funding/#our-sponsors -[funding]: community/funding.md +[funding]: funding.md diff --git a/docs/community/3.11-announcement.md b/docs/community/3.11-announcement.md new file mode 100644 index 000000000..83dd636d1 --- /dev/null +++ b/docs/community/3.11-announcement.md @@ -0,0 +1,117 @@ + + +# Django REST framework 3.11 + +The 3.11 release adds support for Django 3.0. + +* Our supported Python versions are now: 3.5, 3.6, 3.7, and 3.8. +* Our supported Django versions are now: 1.11, 2.0, 2.1, 2.2, and 3.0. + +This release will be the last to support Python 3.5 or Django 1.11. + +## OpenAPI Schema Generation Improvements + +The OpenAPI schema generation continues to mature. Some highlights in 3.11 +include: + +* Automatic mapping of Django REST Framework renderers and parsers into OpenAPI + request and response media-types. +* Improved mapping JSON schema mapping types, for example in HStoreFields, and + with large integer values. +* Porting of the old CoreAPI parsing of docstrings to form OpenAPI operation + descriptions. + +In this example view operation descriptions for the `get` and `post` methods will +be extracted from the class docstring: + +```python +class DocStringExampleListView(APIView): +""" +get: A description of my GET operation. +post: A description of my POST operation. +""" + permission_classes = [permissions.IsAuthenticatedOrReadOnly] + + def get(self, request, *args, **kwargs): + ... + + def post(self, request, *args, **kwargs): + ... +``` + +## Validator / Default Context + +In some circumstances a Validator class or a Default class may need to access the serializer field with which it is called, or the `.context` with which the serializer was instantiated. In particular: + +* Uniqueness validators need to be able to determine the name of the field to which they are applied, in order to run an appropriate database query. +* The `CurrentUserDefault` needs to be able to determine the context with which the serializer was instantiated, in order to return the current user instance. + +Previous our approach to this was that implementations could include a `set_context` method, which would be called prior to validation. However this approach had issues with potential race conditions. We have now move this approach into a pending deprecation state. It will continue to function, but will be escalated to a deprecated state in 3.12, and removed entirely in 3.13. + +Instead, validators or defaults which require the serializer context, should include a `requires_context = True` attribute on the class. + +The `__call__` method should then include an additional `serializer_field` argument. + +Validator implementations will look like this: + +```python +class CustomValidator: + requires_context = True + + def __call__(self, value, serializer_field): + ... +``` + +Default implementations will look like this: + +```python +class CustomDefault: + requires_context = True + + def __call__(self, serializer_field): + ... +``` + +--- + +## Funding + +REST framework is a *collaboratively funded project*. If you use +REST framework commercially we strongly encourage you to invest in its +continued development by **[signing up for a paid plan][funding]**. + +*Every single sign-up helps us make REST framework long-term financially sustainable.* + +
+ + +*Many thanks to all our [wonderful sponsors][sponsors], and in particular to our premium backers, [Sentry](https://getsentry.com/welcome/), [Stream](https://getstream.io/?utm_source=drf&utm_medium=banner&utm_campaign=drf), [ESG](https://software.esg-usa.com/), [Rollbar](https://rollbar.com/?utm_source=django&utm_medium=sponsorship&utm_campaign=freetrial), [Cadre](https://cadre.com), [Kloudless](https://hubs.ly/H0f30Lf0), [Lights On Software](https://lightsonsoftware.com), and [Retool](https://retool.com/?utm_source=djangorest&utm_medium=sponsorship).* + +[sponsors]: https://fund.django-rest-framework.org/topics/funding/#our-sponsors +[funding]: funding.md diff --git a/docs/community/release-notes.md b/docs/community/release-notes.md index 283dbae67..4be05d56b 100644 --- a/docs/community/release-notes.md +++ b/docs/community/release-notes.md @@ -1,9 +1,5 @@ # Release Notes -> Release Early, Release Often -> -> — Eric S. Raymond, [The Cathedral and the Bazaar][cite]. - ## Versioning 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. diff --git a/docs/community/third-party-packages.md b/docs/community/third-party-packages.md index 4d0043252..baa30fd0c 100644 --- a/docs/community/third-party-packages.md +++ b/docs/community/third-party-packages.md @@ -270,6 +270,7 @@ To submit new content, [open an issue][drf-create-issue] or [create a pull reque * [django-rest-framework-condition][django-rest-framework-condition] - Decorators for managing HTTP cache headers for Django REST framework (ETag and Last-modified). * [django-rest-witchcraft][django-rest-witchcraft] - Provides DRF integration with SQLAlchemy with SQLAlchemy model serializers/viewsets and a bunch of other goodies * [djangorestframework-mvt][djangorestframework-mvt] - An extension for creating views that serve Postgres data as Map Box Vector Tiles. +* [drf-viewset-profiler][drf-viewset-profiler] - Lib to profile all methods from a viewset line by line. * [djangorestframework-features][djangorestframework-features] - Advanced schema generation and more based on named features. [cite]: http://www.software-ecosystems.com/Software_Ecosystems/Ecosystems.html @@ -351,4 +352,5 @@ To submit new content, [open an issue][drf-create-issue] or [create a pull reque [django-restql]: https://github.com/yezyilomo/django-restql [djangorestframework-mvt]: https://github.com/corteva/djangorestframework-mvt [django-rest-framework-guardian]: https://github.com/rpkilby/django-rest-framework-guardian +[drf-viewset-profiler]: https://github.com/fvlima/drf-viewset-profiler [djangorestframework-features]: https://github.com/cloudcode-hungary/django-rest-framework-features/ diff --git a/docs/index.md b/docs/index.md index e06b21dff..bccc1fb46 100644 --- a/docs/index.md +++ b/docs/index.md @@ -52,7 +52,7 @@ Some reasons you might want to use REST framework: * [Authentication policies][authentication] including packages for [OAuth1a][oauth1-section] and [OAuth2][oauth2-section]. * [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]. +* Extensive documentation, and [great community support][group]. * Used and trusted by internationally recognised companies including [Mozilla][mozilla], [Red Hat][redhat], [Heroku][heroku], and [Eventbrite][eventbrite]. --- @@ -85,8 +85,8 @@ continued development by **[signing up for a paid plan][funding]**. REST framework requires the following: -* Python (3.5, 3.6, 3.7) -* Django (1.11, 2.0, 2.1, 2.2) +* Python (3.5, 3.6, 3.7, 3.8) +* Django (1.11, 2.0, 2.1, 2.2, 3.0) We **highly recommend** and only officially support the latest patch release of each Python and Django series. diff --git a/docs/topics/api-clients.md b/docs/topics/api-clients.md index 3fd560634..b020c380a 100644 --- a/docs/topics/api-clients.md +++ b/docs/topics/api-clients.md @@ -384,7 +384,7 @@ First, install the API documentation views. These will include the schema resour urlpatterns = [ ... - url(r'^docs/', include_docs_urls(title='My API service')) + url(r'^docs/', include_docs_urls(title='My API service'), name='api-docs'), ] Once the API documentation URLs are installed, you'll be able to include both the required JavaScript resources. Note that the ordering of these two lines is important, as the schema loading requires CoreAPI to already be installed. @@ -401,14 +401,14 @@ Once the API documentation URLs are installed, you'll be able to include both th The `coreapi` library, and the `schema` object will now both be available on the `window` instance. - const coreapi = window.coreapi - const schema = window.schema + const coreapi = window.coreapi; + const schema = window.schema; ## Instantiating a client In order to interact with the API you'll need a client instance. - var client = new coreapi.Client() + var client = new coreapi.Client(); Typically you'll also want to provide some authentication credentials when instantiating the client. @@ -421,9 +421,9 @@ the user to login, and then instantiate a client using session authentication: let auth = new coreapi.auth.SessionAuthentication({ csrfCookieName: 'csrftoken', - csrfHeaderName: 'X-CSRFToken' - }) - let client = new coreapi.Client({auth: auth}) + csrfHeaderName: 'X-CSRFToken', + }); + let client = new coreapi.Client({auth: auth}); The authentication scheme will handle including a CSRF header in any outgoing requests for unsafe HTTP methods. @@ -434,10 +434,10 @@ The `TokenAuthentication` class can be used to support REST framework's built-in `TokenAuthentication`, as well as OAuth and JWT schemes. let auth = new coreapi.auth.TokenAuthentication({ - scheme: 'JWT' - token: '