diff --git a/README.md b/README.md index 8774bc854a..9591bdc17b 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/community/3.10-announcement.md b/docs/community/3.10-announcement.md index 578e900dc1..19748aa40d 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 0000000000..83dd636d19 --- /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/index.md b/docs/index.md index e06b21dffd..bccc1fb46e 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/mkdocs.yml b/mkdocs.yml index 83a345a3d7..484971a715 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -66,6 +66,7 @@ nav: - 'Contributing to REST framework': 'community/contributing.md' - 'Project management': 'community/project-management.md' - 'Release Notes': 'community/release-notes.md' + - '3.11 Announcement': 'community/3.11-announcement.md' - '3.10 Announcement': 'community/3.10-announcement.md' - '3.9 Announcement': 'community/3.9-announcement.md' - '3.8 Announcement': 'community/3.8-announcement.md' diff --git a/rest_framework/__init__.py b/rest_framework/__init__.py index fceee6817d..b6f3f65ceb 100644 --- a/rest_framework/__init__.py +++ b/rest_framework/__init__.py @@ -8,7 +8,7 @@ """ __title__ = 'Django REST framework' -__version__ = '3.10.3' +__version__ = '3.11.0' __author__ = 'Tom Christie' __license__ = 'BSD 3-Clause' __copyright__ = 'Copyright 2011-2019 Encode OSS Ltd' diff --git a/rest_framework/renderers.py b/rest_framework/renderers.py index 9a6f3c3c57..29ac90ea8e 100644 --- a/rest_framework/renderers.py +++ b/rest_framework/renderers.py @@ -16,7 +16,6 @@ from django.core.paginator import Page from django.http.multipartparser import parse_header from django.template import engines, loader -from django.test.client import encode_multipart from django.urls import NoReverseMatch from django.utils.html import mark_safe @@ -902,6 +901,8 @@ class MultiPartRenderer(BaseRenderer): BOUNDARY = 'BoUnDaRyStRiNg' def render(self, data, accepted_media_type=None, renderer_context=None): + from django.test.client import encode_multipart + if hasattr(data, 'items'): for key, value in data.items(): assert not isinstance(value, dict), (