diff --git a/docs/api-guide/caching.md b/docs/api-guide/caching.md index 502a0a9a9..96517b15e 100644 --- a/docs/api-guide/caching.md +++ b/docs/api-guide/caching.md @@ -17,11 +17,16 @@ other cache decorators such as [`cache_page`][page] and [`vary_on_cookie`][cookie]. ```python +from django.utils.decorators import method_decorator +from django.views.decorators.cache import cache_page +from django.views.decorators.vary import vary_on_cookie + from rest_framework.response import Response from rest_framework.views import APIView from rest_framework import viewsets -class UserViewSet(viewsets.Viewset): + +class UserViewSet(viewsets.ViewSet): # Cache requested url for each user for 2 hours @method_decorator(cache_page(60*60*2)) @@ -32,6 +37,7 @@ class UserViewSet(viewsets.Viewset): } return Response(content) + class PostView(APIView): # Cache page for the requested url diff --git a/docs/api-guide/fields.md b/docs/api-guide/fields.md index 92c692bf5..29cb5aec9 100644 --- a/docs/api-guide/fields.md +++ b/docs/api-guide/fields.md @@ -713,7 +713,7 @@ the coordinate pair: fields = ['label', 'coordinates'] Note that this example doesn't handle validation. Partly for that reason, in a -real project, the coordinate nesting might be better handled with a nested serialiser +real project, the coordinate nesting might be better handled with a nested serializer using `source='*'`, with two `IntegerField` instances, each with their own `source` pointing to the relevant field. @@ -746,7 +746,7 @@ suitable for updating our target object. With `source='*'`, the return from ('y_coordinate', 4), ('x_coordinate', 3)]) -For completeness lets do the same thing again but with the nested serialiser +For completeness lets do the same thing again but with the nested serializer approach suggested above: class NestedCoordinateSerializer(serializers.Serializer): @@ -768,14 +768,14 @@ declarations. It's our `NestedCoordinateSerializer` that takes `source='*'`. Our new `DataPointSerializer` exhibits the same behaviour as the custom field approach. -Serialising: +Serializing: >>> out_serializer = DataPointSerializer(instance) >>> out_serializer.data ReturnDict([('label', 'testing'), ('coordinates', OrderedDict([('x', 1), ('y', 2)]))]) -Deserialising: +Deserializing: >>> in_serializer = DataPointSerializer(data=data) >>> in_serializer.is_valid() @@ -802,8 +802,8 @@ But we also get the built-in validation for free: {'x': ['A valid integer is required.'], 'y': ['A valid integer is required.']})]) -For this reason, the nested serialiser approach would be the first to try. You -would use the custom field approach when the nested serialiser becomes infeasible +For this reason, the nested serializer approach would be the first to try. You +would use the custom field approach when the nested serializer becomes infeasible or overly complex. diff --git a/docs/api-guide/generic-views.md b/docs/api-guide/generic-views.md index 8d9ead107..a2f19ff2e 100644 --- a/docs/api-guide/generic-views.md +++ b/docs/api-guide/generic-views.md @@ -378,10 +378,6 @@ If you need to generic PUT-as-create behavior you may want to include something 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. - ## Django Rest Multiple Models [Django Rest Multiple Models][django-rest-multiple-models] provides a generic view (and mixin) for sending multiple serialized models and/or querysets via a single API request. @@ -394,5 +390,4 @@ The [django-rest-framework-bulk package][django-rest-framework-bulk] implements [RetrieveModelMixin]: #retrievemodelmixin [UpdateModelMixin]: #updatemodelmixin [DestroyModelMixin]: #destroymodelmixin -[django-rest-framework-bulk]: https://github.com/miki725/django-rest-framework-bulk [django-rest-multiple-models]: https://github.com/MattBroach/DjangoRestMultipleModels diff --git a/docs/api-guide/requests.md b/docs/api-guide/requests.md index 3bc083893..1c336953c 100644 --- a/docs/api-guide/requests.md +++ b/docs/api-guide/requests.md @@ -49,7 +49,7 @@ If a client sends a request with a content-type that cannot be parsed then a `Un # Content negotiation -The request exposes some properties that allow you to determine the result of the content negotiation stage. This allows you to implement behaviour such as selecting a different serialisation schemes for different media types. +The request exposes some properties that allow you to determine the result of the content negotiation stage. This allows you to implement behaviour such as selecting a different serialization schemes for different media types. ## .accepted_renderer diff --git a/docs/api-guide/schemas.md b/docs/api-guide/schemas.md index 76cc0ca4d..ec5366d8e 100644 --- a/docs/api-guide/schemas.md +++ b/docs/api-guide/schemas.md @@ -115,7 +115,6 @@ The `get_schema_view()` helper takes the following keyword arguments: * `renderer_classes`: May be used to pass the set of renderer classes that can be used to render the API root endpoint. - ## Customizing Schema Generation You may customize schema generation at the level of the schema as a whole, or @@ -155,7 +154,7 @@ Returns a dictionary that represents the OpenAPI schema: The `request` argument is optional, and may be used if you want to apply per-user permissions to the resulting schema generation. -This is a good point to override if you want to customise the generated +This is a good point to override if you want to customize the generated dictionary, for example to add custom [specification extensions][openapi-specification-extensions]. @@ -177,21 +176,20 @@ for each view, allowed method, and path. **Note**: For basic `APIView` subclasses, default introspection is essentially limited to the URL kwarg path parameters. For `GenericAPIView` subclasses, which includes all the provided class based views, `AutoSchema` will -attempt to introspect serialiser, pagination and filter fields, as well as +attempt to introspect serializer, pagination and filter fields, as well as provide richer path field descriptions. (The key hooks here are the relevant `GenericAPIView` attributes and methods: `get_serializer`, `pagination_class`, `filter_backends` and so on.) --- -In order to customise the operation generation, you should provide an `AutoSchema` subclass, overriding `get_operation()` as you need: - +In order to customize the operation generation, you should provide an `AutoSchema` subclass, overriding `get_operation()` as you need: from rest_framework.views import APIView from rest_framework.schemas.openapi import AutoSchema class CustomSchema(AutoSchema): - def get_link(...): + def get_operation(...): # Implement custom introspection here (or in other sub-methods) class CustomView(APIView): @@ -219,4 +217,4 @@ project you may adjust `settings.DEFAULT_SCHEMA_CLASS` appropriately. [openapi]: https://github.com/OAI/OpenAPI-Specification [openapi-specification-extensions]: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#specification-extensions -[openapi-operation]: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#operationObject \ No newline at end of file +[openapi-operation]: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#operationObject diff --git a/docs/community/release-notes.md b/docs/community/release-notes.md index cdaa35044..283dbae67 100644 --- a/docs/community/release-notes.md +++ b/docs/community/release-notes.md @@ -222,11 +222,11 @@ Be sure to upgrade to Python 3 before upgrading to Django REST Framework 3.10. def perform_create(self, serializer): serializer.save(owner=self.request.user) - Alternatively you may override `save()` or `create()` or `update()` on the serialiser as appropriate. + Alternatively you may override `save()` or `create()` or `update()` on the serializer as appropriate. * Correct allow_null behaviour when required=False [#5888][gh5888] - Without an explicit `default`, `allow_null` implies a default of `null` for outgoing serialisation. Previously such + Without an explicit `default`, `allow_null` implies a default of `null` for outgoing serialization. Previously such fields were being skipped when read-only or otherwise not required. **Possible backwards compatibility break** if you were relying on such fields being excluded from the outgoing @@ -464,7 +464,7 @@ Be sure to upgrade to Python 3 before upgrading to Django REST Framework 3.10. * Deprecated `exclude_from_schema` on `APIView` and `api_view` decorator. Set `schema = None` or `@schema(None)` as appropriate. [#5422][gh5422] * Timezone-aware `DateTimeField`s now respect active or default `timezone` during serialization, instead of always using UTC. [#5435][gh5435] - Resolves inconsistency whereby instances were serialised with supplied datetime for `create` but UTC for `retrieve`. [#3732][gh3732] + Resolves inconsistency whereby instances were serialized with supplied datetime for `create` but UTC for `retrieve`. [#3732][gh3732] **Possible backwards compatibility break** if you were relying on datetime strings being UTC. Have client interpret datetimes or [set default or active timezone (docs)][djangodocs-set-timezone] to UTC if needed. diff --git a/docs/community/third-party-packages.md b/docs/community/third-party-packages.md index 9d7d09d9b..ea5d6b854 100644 --- a/docs/community/third-party-packages.md +++ b/docs/community/third-party-packages.md @@ -222,7 +222,6 @@ To submit new content, [open an issue][drf-create-issue] or [create a pull reque ### Views -* [djangorestframework-bulk][djangorestframework-bulk] - Implements generic view mixins as well as some common concrete generic views to allow to apply bulk operations via API requests. * [django-rest-multiple-models][django-rest-multiple-models] - Provides a generic view (and mixin) for sending multiple serialized models and/or querysets via a single API request. ### Routers @@ -254,7 +253,7 @@ To submit new content, [open an issue][drf-create-issue] or [create a pull reque ### Misc * [cookiecutter-django-rest][cookiecutter-django-rest] - A cookiecutter template that takes care of the setup and configuration so you can focus on making your REST apis awesome. -* [djangorestrelationalhyperlink][djangorestrelationalhyperlink] - A hyperlinked serialiser that can can be used to alter relationships via hyperlinks, but otherwise like a hyperlink model serializer. +* [djangorestrelationalhyperlink][djangorestrelationalhyperlink] - A hyperlinked serializer that can can be used to alter relationships via hyperlinks, but otherwise like a hyperlink model serializer. * [django-rest-swagger][django-rest-swagger] - An API documentation generator for Swagger UI. * [django-rest-framework-proxy][django-rest-framework-proxy] - Proxy to redirect incoming request to another API server. * [gaiarestframework][gaiarestframework] - Utils for django-rest-framework @@ -305,7 +304,6 @@ To submit new content, [open an issue][drf-create-issue] or [create a pull reque [djangorestframework-hstore]: https://github.com/djangonauts/django-rest-framework-hstore [drf-compound-fields]: https://github.com/estebistec/drf-compound-fields [django-extra-fields]: https://github.com/Hipo/drf-extra-fields -[djangorestframework-bulk]: https://github.com/miki725/django-rest-framework-bulk [django-rest-multiple-models]: https://github.com/MattBroach/DjangoRestMultipleModels [drf-nested-routers]: https://github.com/alanjds/drf-nested-routers [wq.db.rest]: https://wq.io/docs/about-rest diff --git a/docs/coreapi/schemas.md b/docs/coreapi/schemas.md index 6ee620343..69606f853 100644 --- a/docs/coreapi/schemas.md +++ b/docs/coreapi/schemas.md @@ -191,7 +191,7 @@ each view, allowed method and path.) **Note**: For basic `APIView` subclasses, default introspection is essentially limited to the URL kwarg path parameters. For `GenericAPIView` subclasses, which includes all the provided class based views, `AutoSchema` will -attempt to introspect serialiser, pagination and filter fields, as well as +attempt to introspect serializer, pagination and filter fields, as well as provide richer path field descriptions. (The key hooks here are the relevant `GenericAPIView` attributes and methods: `get_serializer`, `pagination_class`, `filter_backends` and so on.) diff --git a/rest_framework/__init__.py b/rest_framework/__init__.py index 4d4225c96..2b96e7336 100644 --- a/rest_framework/__init__.py +++ b/rest_framework/__init__.py @@ -10,7 +10,7 @@ ______ _____ _____ _____ __ __title__ = 'Django REST framework' __version__ = '3.10.3' __author__ = 'Tom Christie' -__license__ = 'BSD 2-Clause' +__license__ = 'BSD 3-Clause' __copyright__ = 'Copyright 2011-2019 Encode OSS Ltd' # Version synonym diff --git a/rest_framework/schemas/openapi.py b/rest_framework/schemas/openapi.py index 09a5598f5..a3970ff7a 100644 --- a/rest_framework/schemas/openapi.py +++ b/rest_framework/schemas/openapi.py @@ -209,7 +209,7 @@ class AutoSchema(ViewInspector): if not is_list_view(path, method, view): return [] - paginator = self._get_pagninator() + paginator = self._get_paginator() if not paginator: return [] @@ -344,6 +344,7 @@ class AutoSchema(ViewInspector): serializers.BooleanField: 'boolean', serializers.JSONField: 'object', serializers.DictField: 'object', + serializers.HStoreField: 'object', } return {'type': FIELD_CLASS_SCHEMA_TYPE.get(field.__class__, 'string')} @@ -429,7 +430,7 @@ class AutoSchema(ViewInspector): schema['maximum'] = int(digits * '9') + 1 schema['minimum'] = -schema['maximum'] - def _get_pagninator(self): + def _get_paginator(self): pagination_class = getattr(self.view, 'pagination_class', None) if pagination_class: return pagination_class() @@ -502,7 +503,7 @@ class AutoSchema(ViewInspector): 'type': 'array', 'items': item_schema, } - paginator = self._get_pagninator() + paginator = self._get_paginator() if paginator: response_schema = paginator.get_paginated_response_schema(response_schema) else: diff --git a/tests/schemas/test_openapi.py b/tests/schemas/test_openapi.py index e1d29f6fe..78c00d985 100644 --- a/tests/schemas/test_openapi.py +++ b/tests/schemas/test_openapi.py @@ -462,6 +462,22 @@ class TestOperationIntrospection(TestCase): assert properties['date']['format'] == 'date' assert properties['datetime']['format'] == 'date-time' + def test_serializer_hstorefield(self): + path = '/' + method = 'GET' + view = create_view( + views.ExampleGenericAPIView, + method, + create_request(path), + ) + inspector = AutoSchema() + inspector.view = view + + responses = inspector._get_responses(path, method) + response_schema = responses['200']['content']['application/json']['schema'] + properties = response_schema['items']['properties'] + assert properties['hstore']['type'] == 'object' + def test_serializer_validators(self): path = '/' method = 'GET' diff --git a/tests/schemas/views.py b/tests/schemas/views.py index d1fc75eb8..6b83e5bde 100644 --- a/tests/schemas/views.py +++ b/tests/schemas/views.py @@ -33,6 +33,7 @@ class ExampleDetailView(APIView): class ExampleSerializer(serializers.Serializer): date = serializers.DateField() datetime = serializers.DateTimeField() + hstore = serializers.HStoreField() class ExampleGenericAPIView(generics.GenericAPIView): diff --git a/tests/test_serializer.py b/tests/test_serializer.py index 0d4b50c1d..fab0472b9 100644 --- a/tests/test_serializer.py +++ b/tests/test_serializer.py @@ -555,7 +555,7 @@ class TestDefaultOutput: bar = serializers.CharField(source='foo.bar', allow_null=True) optional = serializers.CharField(required=False, allow_null=True) - # allow_null=True should imply default=None when serialising: + # allow_null=True should imply default=None when serializing: assert Serializer({'foo': None}).data == {'foo': None, 'bar': None, 'optional': None, }