mirror of
https://github.com/encode/django-rest-framework.git
synced 2024-11-25 11:04:02 +03:00
Version 3.11 (#7083)
* Version 3.11 * Added notes on OpenAPI changes for 3.11. * Minor docs tweaking * Update package version and supported versions * Use a lazy import for django.test.client.encode_mutlipart. Closes #7078
This commit is contained in:
parent
3c1428ff79
commit
de497a9bf1
|
@ -54,8 +54,8 @@ There is a live example API for testing purposes, [available here][sandbox].
|
||||||
|
|
||||||
# Requirements
|
# Requirements
|
||||||
|
|
||||||
* Python (3.5, 3.6, 3.7)
|
* Python (3.5, 3.6, 3.7, 3.8)
|
||||||
* Django (1.11, 2.0, 2.1, 2.2)
|
* Django (1.11, 2.0, 2.1, 2.2, 3.0)
|
||||||
|
|
||||||
We **highly recommend** and only officially support the latest patch release of
|
We **highly recommend** and only officially support the latest patch release of
|
||||||
each Python and Django series.
|
each Python and Django series.
|
||||||
|
|
|
@ -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
|
[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
|
[sponsors]: https://fund.django-rest-framework.org/topics/funding/#our-sponsors
|
||||||
[funding]: community/funding.md
|
[funding]: funding.md
|
||||||
|
|
117
docs/community/3.11-announcement.md
Normal file
117
docs/community/3.11-announcement.md
Normal file
|
@ -0,0 +1,117 @@
|
||||||
|
<style>
|
||||||
|
.promo li a {
|
||||||
|
float: left;
|
||||||
|
width: 130px;
|
||||||
|
height: 20px;
|
||||||
|
text-align: center;
|
||||||
|
margin: 10px 30px;
|
||||||
|
padding: 150px 0 0 0;
|
||||||
|
background-position: 0 50%;
|
||||||
|
background-size: 130px auto;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
font-size: 120%;
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
.promo li {
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
# 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.*
|
||||||
|
|
||||||
|
<ul class="premium-promo promo">
|
||||||
|
<li><a href="https://getsentry.com/welcome/" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/sentry130.png)">Sentry</a></li>
|
||||||
|
<li><a href="https://getstream.io/try-the-api/?utm_source=drf&utm_medium=banner&utm_campaign=drf" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/stream-130.png)">Stream</a></li>
|
||||||
|
<li><a href="https://software.esg-usa.com" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/esg-new-logo.png)">ESG</a></li>
|
||||||
|
<li><a href="https://rollbar.com" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/rollbar2.png)">Rollbar</a></li>
|
||||||
|
<li><a href="https://cadre.com" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/cadre.png)">Cadre</a></li>
|
||||||
|
<li><a href="https://hubs.ly/H0f30Lf0" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/kloudless-plus-text.png)">Kloudless</a></li>
|
||||||
|
<li><a href="https://lightsonsoftware.com" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/lightson-dark.png)">Lights On Software</a></li>
|
||||||
|
<li><a href="https://retool.com/?utm_source=djangorest&utm_medium=sponsorship" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/retool-sidebar.png)">Retool</a></li>
|
||||||
|
</ul>
|
||||||
|
<div style="clear: both; padding-bottom: 20px;"></div>
|
||||||
|
|
||||||
|
*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
|
|
@ -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].
|
* [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.
|
* [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].
|
* 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].
|
* 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:
|
REST framework requires the following:
|
||||||
|
|
||||||
* Python (3.5, 3.6, 3.7)
|
* Python (3.5, 3.6, 3.7, 3.8)
|
||||||
* Django (1.11, 2.0, 2.1, 2.2)
|
* Django (1.11, 2.0, 2.1, 2.2, 3.0)
|
||||||
|
|
||||||
We **highly recommend** and only officially support the latest patch release of
|
We **highly recommend** and only officially support the latest patch release of
|
||||||
each Python and Django series.
|
each Python and Django series.
|
||||||
|
|
|
@ -66,6 +66,7 @@ nav:
|
||||||
- 'Contributing to REST framework': 'community/contributing.md'
|
- 'Contributing to REST framework': 'community/contributing.md'
|
||||||
- 'Project management': 'community/project-management.md'
|
- 'Project management': 'community/project-management.md'
|
||||||
- 'Release Notes': 'community/release-notes.md'
|
- 'Release Notes': 'community/release-notes.md'
|
||||||
|
- '3.11 Announcement': 'community/3.11-announcement.md'
|
||||||
- '3.10 Announcement': 'community/3.10-announcement.md'
|
- '3.10 Announcement': 'community/3.10-announcement.md'
|
||||||
- '3.9 Announcement': 'community/3.9-announcement.md'
|
- '3.9 Announcement': 'community/3.9-announcement.md'
|
||||||
- '3.8 Announcement': 'community/3.8-announcement.md'
|
- '3.8 Announcement': 'community/3.8-announcement.md'
|
||||||
|
|
|
@ -8,7 +8,7 @@ ______ _____ _____ _____ __
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__title__ = 'Django REST framework'
|
__title__ = 'Django REST framework'
|
||||||
__version__ = '3.10.3'
|
__version__ = '3.11.0'
|
||||||
__author__ = 'Tom Christie'
|
__author__ = 'Tom Christie'
|
||||||
__license__ = 'BSD 3-Clause'
|
__license__ = 'BSD 3-Clause'
|
||||||
__copyright__ = 'Copyright 2011-2019 Encode OSS Ltd'
|
__copyright__ = 'Copyright 2011-2019 Encode OSS Ltd'
|
||||||
|
|
|
@ -16,7 +16,6 @@ from django.core.exceptions import ImproperlyConfigured
|
||||||
from django.core.paginator import Page
|
from django.core.paginator import Page
|
||||||
from django.http.multipartparser import parse_header
|
from django.http.multipartparser import parse_header
|
||||||
from django.template import engines, loader
|
from django.template import engines, loader
|
||||||
from django.test.client import encode_multipart
|
|
||||||
from django.urls import NoReverseMatch
|
from django.urls import NoReverseMatch
|
||||||
from django.utils.html import mark_safe
|
from django.utils.html import mark_safe
|
||||||
|
|
||||||
|
@ -902,6 +901,8 @@ class MultiPartRenderer(BaseRenderer):
|
||||||
BOUNDARY = 'BoUnDaRyStRiNg'
|
BOUNDARY = 'BoUnDaRyStRiNg'
|
||||||
|
|
||||||
def render(self, data, accepted_media_type=None, renderer_context=None):
|
def render(self, data, accepted_media_type=None, renderer_context=None):
|
||||||
|
from django.test.client import encode_multipart
|
||||||
|
|
||||||
if hasattr(data, 'items'):
|
if hasattr(data, 'items'):
|
||||||
for key, value in data.items():
|
for key, value in data.items():
|
||||||
assert not isinstance(value, dict), (
|
assert not isinstance(value, dict), (
|
||||||
|
|
Loading…
Reference in New Issue
Block a user