mirror of
https://github.com/encode/django-rest-framework.git
synced 2024-11-25 11:04:02 +03:00
Version 3.9 (#6247)
* Release notes to5174a26ec9
* Update version for v3.9.0 * Removed exclude_from_schema per deprecation policy. * Updated list_route() and detail_route() deprecations. * Weakened to PendingDeprecationWarning for `base_name` cc @rpkilby. * Add (beginning of) 3.9 release announcement. @tomchristie: Input on OpenAPI and What’s Next very welcome! :) * Add announcement section for Extra Actions in Browsable API * Update release notes and add deprecation note for Django Guardian backend. * Add release note for #6073 * Add release notes todd19a44583
* Adding release notes * Update 3.9 announcement * Add Oct 18 release date
This commit is contained in:
parent
28040b3bda
commit
2c9c0f1b7f
212
docs/community/3.9-announcement.md
Normal file
212
docs/community/3.9-announcement.md
Normal file
|
@ -0,0 +1,212 @@
|
|||
<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.9
|
||||
|
||||
The 3.9 release gives access to _extra actions_ in the Browsable API, introduces composable permissions and built-in [OpenAPI][openapi] schema support. (Formerly known as Swagger)
|
||||
|
||||
---
|
||||
|
||||
## Funding
|
||||
|
||||
If you use REST framework commercially and would like to see this work continue, we strongly encourage you to invest in its continued development by
|
||||
**[signing up for a paid plan][funding]**.
|
||||
|
||||
|
||||
<ul class="premium-promo promo">
|
||||
<li><a href="http://jobs.rover.com/" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/rover_130x130.png)">Rover.com</a></li>
|
||||
<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://auklet.io" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/auklet-new.png)">Auklet</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://loadimpact.com/?utm_campaign=Sponsorship%20links&utm_source=drf&utm_medium=drf" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/load-impact.png)">Load Impact</a></li>
|
||||
<li><a href="https://hubs.ly/H0f30Lf0" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/kloudless.png)">Kloudless</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, [Rover](http://jobs.rover.com/), [Sentry](https://getsentry.com/welcome/), [Stream](https://getstream.io/?utm_source=drf&utm_medium=banner&utm_campaign=drf), [Auklet](https://auklet.io/), [Rollbar](https://rollbar.com), [Cadre](https://cadre.com), [Load Impact](https://loadimpact.com/?utm_campaign=Sponsorship%20links&utm_source=drf&utm_medium=drf), and [Kloudless](https://hubs.ly/H0f30Lf0).*
|
||||
|
||||
---
|
||||
|
||||
## Built-in OpenAPI schema support
|
||||
|
||||
REST framework now has a first-pass at directly including OpenAPI schema support. (Formerly known as Swagger)
|
||||
|
||||
Specifically:
|
||||
|
||||
* There are now `OpenAPIRenderer`, and `JSONOpenAPIRenderer` classes that deal with encoding `coreapi.Document` instances into OpenAPI YAML or OpenAPI JSON.
|
||||
* The `get_schema_view(...)` method now defaults to OpenAPI YAML, with CoreJSON as a secondary
|
||||
option if it is selected via HTTP content negotiation.
|
||||
* There is a new management command `generateschema`, which you can use to dump
|
||||
the schema into your repository.
|
||||
|
||||
Here's an example of adding an OpenAPI schema to the URL conf:
|
||||
|
||||
```python
|
||||
from rest_framework.schemas import get_schema_view
|
||||
from rest_framework.renderers import JSONOpenAPIRenderer
|
||||
|
||||
schema_view = get_schema_view(
|
||||
title='Server Monitoring API',
|
||||
url='https://www.example.org/api/',
|
||||
renderer_classes=[JSONOpenAPIRenderer]
|
||||
)
|
||||
|
||||
urlpatterns = [
|
||||
url('^schema.json$', schema_view),
|
||||
...
|
||||
]
|
||||
```
|
||||
|
||||
And here's how you can use the `generateschema` management command:
|
||||
|
||||
```shell
|
||||
$ python manage.py generateschema --format openapi > schema.yml
|
||||
```
|
||||
|
||||
There's lots of different tooling that you can use for working with OpenAPI
|
||||
schemas. One option that we're working on is the [API Star](https://docs.apistar.com/)
|
||||
command line tool.
|
||||
|
||||
You can use `apistar` to validate your API schema:
|
||||
|
||||
```shell
|
||||
$ apistar validate --path schema.json --format openapi
|
||||
✓ Valid OpenAPI schema.
|
||||
```
|
||||
|
||||
Or to build API documentation:
|
||||
|
||||
```shell
|
||||
$ apistar docs --path schema.json --format openapi
|
||||
✓ Documentation built at "build/index.html".
|
||||
```
|
||||
|
||||
API Star also includes a [dynamic client library](https://docs.apistar.com/client-library/)
|
||||
that uses an API schema to automatically provide a client library interface for making requests.
|
||||
|
||||
## Composable permission classes
|
||||
|
||||
You can now compose permission classes using the and/or operators, `&` and `|`.
|
||||
|
||||
For example...
|
||||
|
||||
```python
|
||||
permission_classes = [IsAuthenticated & (ReadOnly | IsAdmin)]
|
||||
```
|
||||
|
||||
If you're using custom permission classes then make sure that you are subclassing
|
||||
from `BasePermission` in order to enable this support.
|
||||
|
||||
## ViewSet _Extra Actions_ available in the Browsable API
|
||||
|
||||
Following the introduction of the `action` decorator in v3.8, _extra actions_ defined on a ViewSet are now available
|
||||
from the Browsable API.
|
||||
|
||||
![Extra Actions displayed in the Browsable API](https://user-images.githubusercontent.com/2370209/32976956-1ca9ab7e-cbf1-11e7-981a-a20cb1e83d63.png)
|
||||
|
||||
When defined, a dropdown of "Extra Actions", appropriately filtered to detail/non-detail actions, is displayed.
|
||||
|
||||
---
|
||||
|
||||
## Supported Versions
|
||||
|
||||
REST framework 3.9 supports Django versions 1.11, 2.0, and 2.1.
|
||||
|
||||
---
|
||||
|
||||
## Deprecations
|
||||
|
||||
### `DjangoObjectPermissionsFilter` moved to third-party package.
|
||||
|
||||
The `DjangoObjectPermissionsFilter` class is pending deprecation, will be deprecated in 3.10 and removed entirely in 3.11.
|
||||
|
||||
It has been moved to the third-party [`djangorestframework-guardian`](https://github.com/rpkilby/django-rest-framework-guardian)
|
||||
package. Please use this instead.
|
||||
|
||||
### Router argument/method renamed to use `basename` for consistency.
|
||||
|
||||
* The `Router.register` `base_name` argument has been renamed in favor of `basename`.
|
||||
* The `Router.get_default_base_name` method has been renamed in favor of `Router.get_default_basename`. [#5990][gh5990]
|
||||
|
||||
See [#5990][gh5990].
|
||||
|
||||
[gh5990]: https://github.com/encode/django-rest-framework/pull/5990
|
||||
|
||||
`base_name` and `get_default_base_name()` are pending deprecation. They will be deprecated in 3.10 and removed entirely in 3.11.
|
||||
|
||||
### `action` decorator replaces `list_route` and `detail_route`
|
||||
|
||||
Both `list_route` and `detail_route` are now deprecated in favour of the single `action` decorator.
|
||||
They will be removed entirely in 3.10.
|
||||
|
||||
The `action` decorator takes a boolean `detail` argument.
|
||||
|
||||
* Replace `detail_route` uses with `@action(detail=True)`.
|
||||
* Replace `list_route` uses with `@action(detail=False)`.
|
||||
|
||||
### `exclude_from_schema`
|
||||
|
||||
Both `APIView.exclude_from_schema` and the `exclude_from_schema` argument to the `@api_view` have now been removed.
|
||||
|
||||
For `APIView` you should instead set a `schema = None` attribute on the view class.
|
||||
|
||||
For function based views the `@schema` decorator can be used to exclude the view from the schema, by using `@schema(None)`.
|
||||
|
||||
---
|
||||
|
||||
## Minor fixes and improvements
|
||||
|
||||
There are a large number of minor fixes and improvements in this release. See the [release notes](release-notes.md) page for a complete listing.
|
||||
|
||||
|
||||
## What's next
|
||||
|
||||
We're planning to iteratively working towards OpenAPI becoming the standard schema
|
||||
representation. This will mean that the `coreapi` dependency will gradually become
|
||||
removed, and we'll instead generate the schema directly, rather than building
|
||||
a CoreAPI `Document` object.
|
||||
|
||||
OpenAPI has clearly become the standard for specifying Web APIs, so there's not
|
||||
much value any more in our schema-agnostic document model. Making this change
|
||||
will mean that we'll more easily be able to take advantage of the full set of
|
||||
OpenAPI functionality.
|
||||
|
||||
This will also make a wider range of tooling available.
|
||||
|
||||
We'll focus on continuing to develop the [API Star](https://docs.apistar.com/)
|
||||
library and client tool into a recommended option for generating API docs,
|
||||
validating API schemas, and providing a dynamic client library.
|
||||
|
||||
There's also a huge amount of ongoing work on maturing the ASGI landscape,
|
||||
with the possibility that some of this work will eventually [feed back into
|
||||
Django](https://www.aeracode.org/2018/06/04/django-async-roadmap/).
|
||||
|
||||
There will be further work on the [Uvicorn](https://www.uvicorn.org/)
|
||||
webserver, as well as lots of functionality planned for the [Starlette](https://www.starlette.io/)
|
||||
web framework, which is building a foundational set of tooling for working with
|
||||
ASGI.
|
||||
|
||||
|
||||
[funding]: funding.md
|
||||
[gh5886]: https://github.com/encode/django-rest-framework/issues/5886
|
||||
[gh5705]: https://github.com/encode/django-rest-framework/issues/5705
|
||||
[openapi]: https://www.openapis.org/
|
||||
[sponsors]: https://fund.django-rest-framework.org/topics/funding/#our-sponsors
|
|
@ -42,11 +42,52 @@ You can determine your currently installed version using `pip show`:
|
|||
|
||||
### 3.9.0
|
||||
|
||||
**Date**: Unreleased
|
||||
**Date**: [18st October 2018][3.9.0-milestone]
|
||||
|
||||
* Improvements to ViewSet extra actions [#5605][gh5605]
|
||||
* Fix `action` support for ViewSet suffixes [#6081][gh6081]
|
||||
* Allow `action` docs sections [#6060][gh6060]
|
||||
* Deprecate the `Router.register` `base_name` argument in favor of `basename`. [#5990][gh5990]
|
||||
* Deprecate the `Router.get_default_base_name` method in favor of `Router.get_default_basename`. [#5990][gh5990]
|
||||
* Change `CharField` to disallow null bytes. [#6073][gh6073]
|
||||
To revert to the old behavior, subclass `CharField` and remove `ProhibitNullCharactersValidator` from the validators.
|
||||
```python
|
||||
class NullableCharField(serializers.CharField):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.validators = [v for v in self.validators if not isinstance(v, ProhibitNullCharactersValidator)]
|
||||
```
|
||||
* Add `OpenAPIRenderer` and `generate_schema` management command. [#6229][gh6229]
|
||||
* Add OpenAPIRenderer by default, and add schema docs. [#6233][gh6233]
|
||||
* Allow permissions to be composed [#5753][gh5753]
|
||||
* Allow nullable BooleanField in Django 2.1 [#6183][gh6183]
|
||||
* Add testing of Python 3.7 support [#6141][gh6141]
|
||||
* Test using Django 2.1 final release. [#6109][gh6109]
|
||||
* Added djangorestframework-datatables to third-party packages [#5931][gh5931]
|
||||
* Change ISO 8601 date format to exclude year/month [#5936][gh5936]
|
||||
* Update all pypi.python.org URLs to pypi.org [#5942][gh5942]
|
||||
* Ensure that html forms (multipart form data) respect optional fields [#5927][gh5927]
|
||||
* Allow hashing of ErrorDetail. [#5932][gh5932]
|
||||
* Correct schema parsing for JSONField [#5878][gh5878]
|
||||
* Render descriptions (from help_text) using safe [#5869][gh5869]
|
||||
* Removed input value from deault_error_message [#5881][gh5881]
|
||||
* Added min_value/max_value support in DurationField [#5643][gh5643]
|
||||
* Fixed instance being overwritten in pk-only optimization try/except block [#5747][gh5747]
|
||||
* Fixed AttributeError from items filter when value is None [#5981][gh5981]
|
||||
* Fixed Javascript `e.indexOf` is not a function error [#5982][gh5982]
|
||||
* Fix schemas for extra actions [#5992][gh5992]
|
||||
* Improved get_error_detail to use error_dict/error_list [#5785][gh5785]
|
||||
* Imprvied URLs in Admin renderer [#5988][gh5988]
|
||||
* Add "Community" section to docs, minor cleanup [#5993][gh5993]
|
||||
* Moved guardian imports out of compat [#6054][gh6054]
|
||||
* Deprecate the `DjangoObjectPermissionsFilter` class, moved to the `djangorestframework-guardian` package. [#6075][gh6075]
|
||||
* Drop Django 1.10 support [#5657][gh5657]
|
||||
* Only catch TypeError/ValueError for object lookups [#6028][gh6028]
|
||||
* Handle models without .objects manager in ModelSerializer. [#6111][gh6111]
|
||||
* Improve ModelSerializer.create() error message. [#6112][gh6112]
|
||||
* Fix CSRF cookie check failure when using session auth with django 1.11.6+ [#6113][gh6113]
|
||||
* Updated JWT docs. [#6138][gh6138]
|
||||
* Fix autoescape not getting passed to urlize_quoted_links filter [#6191][gh6191]
|
||||
|
||||
|
||||
## 3.8.x series
|
||||
|
@ -1093,6 +1134,7 @@ For older release notes, [please see the version 2.x documentation][old-release-
|
|||
[3.8.0-milestone]: https://github.com/encode/django-rest-framework/milestone/61?closed=1
|
||||
[3.8.1-milestone]: https://github.com/encode/django-rest-framework/milestone/67?closed=1
|
||||
[3.8.2-milestone]: https://github.com/encode/django-rest-framework/milestone/68?closed=1
|
||||
[3.9.0-milestone]: https://github.com/encode/django-rest-framework/milestone/66?closed=1
|
||||
|
||||
<!-- 3.0.1 -->
|
||||
[gh2013]: https://github.com/encode/django-rest-framework/issues/2013
|
||||
|
@ -1974,5 +2016,39 @@ For older release notes, [please see the version 2.x documentation][old-release-
|
|||
[gh5920]: https://github.com/encode/django-rest-framework/issues/5920
|
||||
|
||||
<!-- 3.9.0 -->
|
||||
[gh6109]: https://github.com/encode/django-rest-framework/issues/6109
|
||||
[gh6141]: https://github.com/encode/django-rest-framework/issues/6141
|
||||
[gh6113]: https://github.com/encode/django-rest-framework/issues/6113
|
||||
[gh6112]: https://github.com/encode/django-rest-framework/issues/6112
|
||||
[gh6111]: https://github.com/encode/django-rest-framework/issues/6111
|
||||
[gh6028]: https://github.com/encode/django-rest-framework/issues/6028
|
||||
[gh5657]: https://github.com/encode/django-rest-framework/issues/5657
|
||||
[gh6054]: https://github.com/encode/django-rest-framework/issues/6054
|
||||
[gh5993]: https://github.com/encode/django-rest-framework/issues/5993
|
||||
[gh5990]: https://github.com/encode/django-rest-framework/issues/5990
|
||||
[gh5988]: https://github.com/encode/django-rest-framework/issues/5988
|
||||
[gh5785]: https://github.com/encode/django-rest-framework/issues/5785
|
||||
[gh5992]: https://github.com/encode/django-rest-framework/issues/5992
|
||||
[gh5605]: https://github.com/encode/django-rest-framework/issues/5605
|
||||
[gh5982]: https://github.com/encode/django-rest-framework/issues/5982
|
||||
[gh5981]: https://github.com/encode/django-rest-framework/issues/5981
|
||||
[gh5747]: https://github.com/encode/django-rest-framework/issues/5747
|
||||
[gh5643]: https://github.com/encode/django-rest-framework/issues/5643
|
||||
[gh5881]: https://github.com/encode/django-rest-framework/issues/5881
|
||||
[gh5869]: https://github.com/encode/django-rest-framework/issues/5869
|
||||
[gh5878]: https://github.com/encode/django-rest-framework/issues/5878
|
||||
[gh5932]: https://github.com/encode/django-rest-framework/issues/5932
|
||||
[gh5927]: https://github.com/encode/django-rest-framework/issues/5927
|
||||
[gh5942]: https://github.com/encode/django-rest-framework/issues/5942
|
||||
[gh5936]: https://github.com/encode/django-rest-framework/issues/5936
|
||||
[gh5931]: https://github.com/encode/django-rest-framework/issues/5931
|
||||
[gh6183]: https://github.com/encode/django-rest-framework/issues/6183
|
||||
[gh6075]: https://github.com/encode/django-rest-framework/issues/6075
|
||||
[gh6138]: https://github.com/encode/django-rest-framework/issues/6138
|
||||
[gh6081]: https://github.com/encode/django-rest-framework/issues/6081
|
||||
[gh6073]: https://github.com/encode/django-rest-framework/issues/6073
|
||||
[gh6191]: https://github.com/encode/django-rest-framework/issues/6191
|
||||
[gh6060]: https://github.com/encode/django-rest-framework/issues/6060
|
||||
[gh6233]: https://github.com/encode/django-rest-framework/issues/6233
|
||||
[gh5753]: https://github.com/encode/django-rest-framework/issues/5753
|
||||
[gh6229]: https://github.com/encode/django-rest-framework/issues/6229
|
||||
|
|
|
@ -65,6 +65,7 @@ pages:
|
|||
- 'Contributing to REST framework': 'community/contributing.md'
|
||||
- 'Project management': 'community/project-management.md'
|
||||
- 'Release Notes': 'community/release-notes.md'
|
||||
- '3.9 Announcement': 'community/3.9-announcement.md'
|
||||
- '3.8 Announcement': 'community/3.8-announcement.md'
|
||||
- '3.7 Announcement': 'community/3.7-announcement.md'
|
||||
- '3.6 Announcement': 'community/3.6-announcement.md'
|
||||
|
|
|
@ -8,7 +8,7 @@ ______ _____ _____ _____ __
|
|||
"""
|
||||
|
||||
__title__ = 'Django REST framework'
|
||||
__version__ = '3.8.2'
|
||||
__version__ = '3.9.0'
|
||||
__author__ = 'Tom Christie'
|
||||
__license__ = 'BSD 2-Clause'
|
||||
__copyright__ = 'Copyright 2011-2018 Tom Christie'
|
||||
|
|
|
@ -17,7 +17,7 @@ from django.utils import six
|
|||
from rest_framework.views import APIView
|
||||
|
||||
|
||||
def api_view(http_method_names=None, exclude_from_schema=False):
|
||||
def api_view(http_method_names=None):
|
||||
"""
|
||||
Decorator that converts a function-based view into an APIView subclass.
|
||||
Takes a list of allowed methods for the view as an argument.
|
||||
|
@ -77,15 +77,8 @@ def api_view(http_method_names=None, exclude_from_schema=False):
|
|||
WrappedAPIView.schema = getattr(func, 'schema',
|
||||
APIView.schema)
|
||||
|
||||
if exclude_from_schema:
|
||||
warnings.warn(
|
||||
"The `exclude_from_schema` argument to `api_view` is deprecated. "
|
||||
"Use the `schema` decorator instead, passing `None`.",
|
||||
DeprecationWarning
|
||||
)
|
||||
WrappedAPIView.exclude_from_schema = exclude_from_schema
|
||||
|
||||
return WrappedAPIView.as_view()
|
||||
|
||||
return decorator
|
||||
|
||||
|
||||
|
@ -230,9 +223,9 @@ def detail_route(methods=None, **kwargs):
|
|||
Used to mark a method on a ViewSet that should be routed for detail requests.
|
||||
"""
|
||||
warnings.warn(
|
||||
"`detail_route` is pending deprecation and will be removed in 3.10 in favor of "
|
||||
"`detail_route` is deprecated and will be removed in 3.10 in favor of "
|
||||
"`action`, which accepts a `detail` bool. Use `@action(detail=True)` instead.",
|
||||
PendingDeprecationWarning, stacklevel=2
|
||||
DeprecationWarning, stacklevel=2
|
||||
)
|
||||
|
||||
def decorator(func):
|
||||
|
@ -248,9 +241,9 @@ def list_route(methods=None, **kwargs):
|
|||
Used to mark a method on a ViewSet that should be routed for list requests.
|
||||
"""
|
||||
warnings.warn(
|
||||
"`list_route` is pending deprecation and will be removed in 3.10 in favor of "
|
||||
"`list_route` is deprecated and will be removed in 3.10 in favor of "
|
||||
"`action`, which accepts a `detail` bool. Use `@action(detail=False)` instead.",
|
||||
PendingDeprecationWarning, stacklevel=2
|
||||
DeprecationWarning, stacklevel=2
|
||||
)
|
||||
|
||||
def decorator(func):
|
||||
|
|
|
@ -40,10 +40,10 @@ DynamicRoute = namedtuple('DynamicRoute', ['url', 'name', 'detail', 'initkwargs'
|
|||
class DynamicDetailRoute(object):
|
||||
def __new__(cls, url, name, initkwargs):
|
||||
warnings.warn(
|
||||
"`DynamicDetailRoute` is pending deprecation and will be removed in 3.10 "
|
||||
"`DynamicDetailRoute` is deprecated and will be removed in 3.10 "
|
||||
"in favor of `DynamicRoute`, which accepts a `detail` boolean. Use "
|
||||
"`DynamicRoute(url, name, True, initkwargs)` instead.",
|
||||
PendingDeprecationWarning, stacklevel=2
|
||||
DeprecationWarning, stacklevel=2
|
||||
)
|
||||
return DynamicRoute(url, name, True, initkwargs)
|
||||
|
||||
|
@ -51,10 +51,10 @@ class DynamicDetailRoute(object):
|
|||
class DynamicListRoute(object):
|
||||
def __new__(cls, url, name, initkwargs):
|
||||
warnings.warn(
|
||||
"`DynamicListRoute` is pending deprecation and will be removed in 3.10 in "
|
||||
"`DynamicListRoute` is deprecated and will be removed in 3.10 in "
|
||||
"favor of `DynamicRoute`, which accepts a `detail` boolean. Use "
|
||||
"`DynamicRoute(url, name, False, initkwargs)` instead.",
|
||||
PendingDeprecationWarning, stacklevel=2
|
||||
DeprecationWarning, stacklevel=2
|
||||
)
|
||||
return DynamicRoute(url, name, False, initkwargs)
|
||||
|
||||
|
@ -77,7 +77,7 @@ def flatten(list_of_lists):
|
|||
|
||||
class RenameRouterMethods(RenameMethodsBase):
|
||||
renamed_methods = (
|
||||
('get_default_base_name', 'get_default_basename', DeprecationWarning),
|
||||
('get_default_base_name', 'get_default_basename', PendingDeprecationWarning),
|
||||
)
|
||||
|
||||
|
||||
|
@ -87,8 +87,8 @@ class BaseRouter(six.with_metaclass(RenameRouterMethods)):
|
|||
|
||||
def register(self, prefix, viewset, basename=None, base_name=None):
|
||||
if base_name is not None:
|
||||
msg = "The `base_name` argument has been deprecated in favor of `basename`."
|
||||
warnings.warn(msg, DeprecationWarning, 2)
|
||||
msg = "The `base_name` argument is pending deprecation in favor of `basename`."
|
||||
warnings.warn(msg, PendingDeprecationWarning, 2)
|
||||
|
||||
assert not (basename and base_name), (
|
||||
"Do not provide both the `basename` and `base_name` arguments.")
|
||||
|
|
|
@ -4,7 +4,6 @@ generators.py # Top-down schema generation
|
|||
See schemas.__init__.py for package overview.
|
||||
"""
|
||||
import re
|
||||
import warnings
|
||||
from collections import Counter, OrderedDict
|
||||
from importlib import import_module
|
||||
|
||||
|
@ -207,14 +206,6 @@ class EndpointEnumerator(object):
|
|||
if not is_api_view(callback):
|
||||
return False # Ignore anything except REST framework views.
|
||||
|
||||
if hasattr(callback.cls, 'exclude_from_schema'):
|
||||
fmt = ("The `{}.exclude_from_schema` attribute is deprecated. "
|
||||
"Set `schema = None` instead.")
|
||||
msg = fmt.format(callback.cls.__name__)
|
||||
warnings.warn(msg, DeprecationWarning)
|
||||
if getattr(callback.cls, 'exclude_from_schema', False):
|
||||
return False
|
||||
|
||||
if callback.cls.schema is None:
|
||||
return False
|
||||
|
||||
|
|
|
@ -290,34 +290,34 @@ class ActionDecoratorTestCase(TestCase):
|
|||
raise NotImplementedError
|
||||
|
||||
def test_detail_route_deprecation(self):
|
||||
with pytest.warns(PendingDeprecationWarning) as record:
|
||||
with pytest.warns(DeprecationWarning) as record:
|
||||
@detail_route()
|
||||
def view(request):
|
||||
raise NotImplementedError
|
||||
|
||||
assert len(record) == 1
|
||||
assert str(record[0].message) == (
|
||||
"`detail_route` is pending deprecation and will be removed in "
|
||||
"`detail_route` is deprecated and will be removed in "
|
||||
"3.10 in favor of `action`, which accepts a `detail` bool. Use "
|
||||
"`@action(detail=True)` instead."
|
||||
)
|
||||
|
||||
def test_list_route_deprecation(self):
|
||||
with pytest.warns(PendingDeprecationWarning) as record:
|
||||
with pytest.warns(DeprecationWarning) as record:
|
||||
@list_route()
|
||||
def view(request):
|
||||
raise NotImplementedError
|
||||
|
||||
assert len(record) == 1
|
||||
assert str(record[0].message) == (
|
||||
"`list_route` is pending deprecation and will be removed in "
|
||||
"`list_route` is deprecated and will be removed in "
|
||||
"3.10 in favor of `action`, which accepts a `detail` bool. Use "
|
||||
"`@action(detail=False)` instead."
|
||||
)
|
||||
|
||||
def test_route_url_name_from_path(self):
|
||||
# pre-3.8 behavior was to base the `url_name` off of the `url_path`
|
||||
with pytest.warns(PendingDeprecationWarning):
|
||||
with pytest.warns(DeprecationWarning):
|
||||
@list_route(url_path='foo_bar')
|
||||
def view(request):
|
||||
raise NotImplementedError
|
||||
|
|
|
@ -495,18 +495,18 @@ class TestBaseNameRename(TestCase):
|
|||
warnings.simplefilter('always')
|
||||
router.register('mock', MockViewSet, 'mock', base_name='mock')
|
||||
|
||||
msg = "The `base_name` argument has been deprecated in favor of `basename`."
|
||||
msg = "The `base_name` argument is pending deprecation in favor of `basename`."
|
||||
assert len(w) == 1
|
||||
assert str(w[0].message) == msg
|
||||
|
||||
def test_base_name_argument_deprecation(self):
|
||||
router = SimpleRouter()
|
||||
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
with pytest.warns(PendingDeprecationWarning) as w:
|
||||
warnings.simplefilter('always')
|
||||
router.register('mock', MockViewSet, base_name='mock')
|
||||
|
||||
msg = "The `base_name` argument has been deprecated in favor of `basename`."
|
||||
msg = "The `base_name` argument is pending deprecation in favor of `basename`."
|
||||
assert len(w) == 1
|
||||
assert str(w[0].message) == msg
|
||||
assert router.registry == [
|
||||
|
@ -529,7 +529,7 @@ class TestBaseNameRename(TestCase):
|
|||
msg = "`CustomRouter.get_default_base_name` method should be renamed `get_default_basename`."
|
||||
|
||||
# Class definition should raise a warning
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
with pytest.warns(PendingDeprecationWarning) as w:
|
||||
warnings.simplefilter('always')
|
||||
|
||||
class CustomRouter(SimpleRouter):
|
||||
|
|
|
@ -1032,38 +1032,6 @@ class SchemaGenerationExclusionTests(TestCase):
|
|||
|
||||
assert should_include == expected
|
||||
|
||||
def test_deprecations(self):
|
||||
with pytest.warns(DeprecationWarning) as record:
|
||||
@api_view(["GET"], exclude_from_schema=True)
|
||||
def view(request):
|
||||
pass
|
||||
|
||||
assert len(record) == 1
|
||||
assert str(record[0].message) == (
|
||||
"The `exclude_from_schema` argument to `api_view` is deprecated. "
|
||||
"Use the `schema` decorator instead, passing `None`."
|
||||
)
|
||||
|
||||
class OldFashionedExcludedView(APIView):
|
||||
exclude_from_schema = True
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
pass
|
||||
|
||||
patterns = [
|
||||
url('^excluded-old-fashioned/$', OldFashionedExcludedView.as_view()),
|
||||
]
|
||||
|
||||
inspector = EndpointEnumerator(patterns)
|
||||
with pytest.warns(DeprecationWarning) as record:
|
||||
inspector.get_api_endpoints()
|
||||
|
||||
assert len(record) == 1
|
||||
assert str(record[0].message) == (
|
||||
"The `OldFashionedExcludedView.exclude_from_schema` attribute is "
|
||||
"deprecated. Set `schema = None` instead."
|
||||
)
|
||||
|
||||
|
||||
@api_view(["GET"])
|
||||
def simple_fbv(request):
|
||||
|
|
Loading…
Reference in New Issue
Block a user