mirror of
				https://github.com/encode/django-rest-framework.git
				synced 2025-11-01 00:17:40 +03:00 
			
		
		
		
	Version 3.14.0 proposal (#8599)
* Version 3.14.0 * Update docs/community/release-notes.md to use proper links. Co-authored-by: Adam Johnson <me@adamj.eu> * Add community announcement page for version 3.14 * Remove deprecated NullBooleanField. * Change openapi _get_reference removal to 3.15 This deprecation was never released in the 3.13.x series and therefore can't be removed at the same time the replacement is released. * Removing deprecated openapi methods. Co-authored-by: Adam Johnson <me@adamj.eu>
This commit is contained in:
		
							parent
							
								
									51f1aff162
								
							
						
					
					
						commit
						b658915846
					
				|  | @ -159,14 +159,6 @@ Corresponds to `django.db.models.fields.BooleanField`. | ||||||
| 
 | 
 | ||||||
| **Signature:** `BooleanField()` | **Signature:** `BooleanField()` | ||||||
| 
 | 
 | ||||||
| ## NullBooleanField |  | ||||||
| 
 |  | ||||||
| A boolean representation that also accepts `None` as a valid value. |  | ||||||
| 
 |  | ||||||
| Corresponds to `django.db.models.fields.NullBooleanField`. |  | ||||||
| 
 |  | ||||||
| **Signature:** `NullBooleanField()` |  | ||||||
| 
 |  | ||||||
| --- | --- | ||||||
| 
 | 
 | ||||||
| # String fields | # String fields | ||||||
|  |  | ||||||
							
								
								
									
										62
									
								
								docs/community/3.14-announcement.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								docs/community/3.14-announcement.md
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,62 @@ | ||||||
|  | <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.14 | ||||||
|  | 
 | ||||||
|  | ## Django 4.1 support | ||||||
|  | 
 | ||||||
|  | The latest release now fully supports Django 4.1. | ||||||
|  | 
 | ||||||
|  | Our requirements are now: | ||||||
|  | 
 | ||||||
|  | * Python 3.6+ | ||||||
|  | * Django 4.1, 4.0, 3.2, 3.1, 2.2 (LTS) | ||||||
|  | 
 | ||||||
|  | ## `raise_exceptions` argument for `is_valid` is now keyword-only. | ||||||
|  | 
 | ||||||
|  | Calling `serializer_instance.is_valid(True)` is no longer acceptable syntax. | ||||||
|  | If you'd like to use the `raise_exceptions` argument, you must use it as a | ||||||
|  | keyword argument. | ||||||
|  | 
 | ||||||
|  | See Pull Request [#7952](https://github.com/encode/django-rest-framework/pull/7952) for more details. | ||||||
|  | 
 | ||||||
|  | ## `ManyRelatedField` supports returning the default when the source attribute doesn't exist. | ||||||
|  | 
 | ||||||
|  | Previously, if you used a serializer field with `many=True` with a dot notated source field | ||||||
|  | that didn't exist, it would raise an `AttributeError`. Now it will return the default or be | ||||||
|  | skipped depending on the other arguments. | ||||||
|  | 
 | ||||||
|  | See Pull Request [#7574](https://github.com/encode/django-rest-framework/pull/7574) for more details. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | ## Make Open API `get_reference` public. | ||||||
|  | 
 | ||||||
|  | Returns a reference to the serializer component. This may be useful if you override `get_schema()`. | ||||||
|  | 
 | ||||||
|  | ## Change semantic of OR of two permission classes. | ||||||
|  | 
 | ||||||
|  | When OR-ing two permissions, the request has to pass either class's `has_permission() and has_object_permission()`. | ||||||
|  | 
 | ||||||
|  | Previously, both class's `has_permission()` was ignored when OR-ing two permissions together. | ||||||
|  | 
 | ||||||
|  | See Pull Request [#7522](https://github.com/encode/django-rest-framework/pull/7522) for more details. | ||||||
|  | 
 | ||||||
|  | ## Minor fixes and improvements | ||||||
|  | 
 | ||||||
|  | There are a number of minor fixes and improvements in this release. See the [release notes](release-notes.md) page for a complete listing. | ||||||
|  | @ -34,6 +34,23 @@ You can determine your currently installed version using `pip show`: | ||||||
| 
 | 
 | ||||||
| --- | --- | ||||||
| 
 | 
 | ||||||
|  | ## 3.14.x series | ||||||
|  | 
 | ||||||
|  | ### 3.14.0 | ||||||
|  | 
 | ||||||
|  | Date: 10th August 2022 | ||||||
|  | 
 | ||||||
|  | * Enforce `is_valid(raise_exception=False)` as a keyword-only argument. [[#7952](https://github.com/encode/django-rest-framework/pull/7952)] | ||||||
|  | * Django 4.1 compatability. [[#8591](https://github.com/encode/django-rest-framework/pull/8591)] | ||||||
|  | * Stop calling `set_context` on Validators. [[#8589](https://github.com/encode/django-rest-framework/pull/8589)] | ||||||
|  | * Return `NotImplemented` from `ErrorDetails.__ne__`. [[#8538](https://github.com/encode/django-rest-framework/pull/8538)] | ||||||
|  | * Don't evaluate `DateTimeField.default_timezone` when a custom timezone is set. [[#8531](https://github.com/encode/django-rest-framework/pull/8531)] | ||||||
|  | * Make relative URLs clickable in Browseable API. [[#8464](https://github.com/encode/django-rest-framework/pull/8464)] | ||||||
|  | * Support `ManyRelatedField` falling back to the default value when the attribute specified by dot notation doesn't exist. Matches `ManyRelatedField.get_attribute` to `Field.get_attribute`. [[#7574](https://github.com/encode/django-rest-framework/pull/7574)] | ||||||
|  | * Make `schemas.openapi.get_reference` public. [[#7515](https://github.com/encode/django-rest-framework/pull/7515)] | ||||||
|  | * Make `ReturnDict` support `dict` union operators on Python 3.9 and later. [[#8302](https://github.com/encode/django-rest-framework/pull/8302)] | ||||||
|  | * Update throttling to check if `request.user` is set before checking if the user is authenticated. [[#8370](https://github.com/encode/django-rest-framework/pull/8370)] | ||||||
|  | 
 | ||||||
| ## 3.13.x series | ## 3.13.x series | ||||||
| 
 | 
 | ||||||
| ### 3.13.1 | ### 3.13.1 | ||||||
|  |  | ||||||
|  | @ -10,7 +10,7 @@ ______ _____ _____ _____    __ | ||||||
| import django | import django | ||||||
| 
 | 
 | ||||||
| __title__ = 'Django REST framework' | __title__ = 'Django REST framework' | ||||||
| __version__ = '3.13.1' | __version__ = '3.14.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' | ||||||
|  | @ -35,3 +35,7 @@ class RemovedInDRF313Warning(DeprecationWarning): | ||||||
| 
 | 
 | ||||||
| class RemovedInDRF314Warning(PendingDeprecationWarning): | class RemovedInDRF314Warning(PendingDeprecationWarning): | ||||||
|     pass |     pass | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class RemovedInDRF315Warning(PendingDeprecationWarning): | ||||||
|  |     pass | ||||||
|  |  | ||||||
|  | @ -5,7 +5,6 @@ import functools | ||||||
| import inspect | import inspect | ||||||
| import re | import re | ||||||
| import uuid | import uuid | ||||||
| import warnings |  | ||||||
| from collections import OrderedDict | from collections import OrderedDict | ||||||
| from collections.abc import Mapping | from collections.abc import Mapping | ||||||
| 
 | 
 | ||||||
|  | @ -30,7 +29,7 @@ from django.utils.ipv6 import clean_ipv6_address | ||||||
| from django.utils.translation import gettext_lazy as _ | from django.utils.translation import gettext_lazy as _ | ||||||
| from pytz.exceptions import InvalidTimeError | from pytz.exceptions import InvalidTimeError | ||||||
| 
 | 
 | ||||||
| from rest_framework import ISO_8601, RemovedInDRF314Warning | from rest_framework import ISO_8601 | ||||||
| from rest_framework.exceptions import ErrorDetail, ValidationError | from rest_framework.exceptions import ErrorDetail, ValidationError | ||||||
| from rest_framework.settings import api_settings | from rest_framework.settings import api_settings | ||||||
| from rest_framework.utils import html, humanize_datetime, json, representation | from rest_framework.utils import html, humanize_datetime, json, representation | ||||||
|  | @ -712,23 +711,6 @@ class BooleanField(Field): | ||||||
|         return bool(value) |         return bool(value) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class NullBooleanField(BooleanField): |  | ||||||
|     initial = None |  | ||||||
| 
 |  | ||||||
|     def __init__(self, **kwargs): |  | ||||||
|         warnings.warn( |  | ||||||
|             "The `NullBooleanField` is deprecated and will be removed starting " |  | ||||||
|             "with 3.14. Instead use the `BooleanField` field and set " |  | ||||||
|             "`allow_null=True` which does the same thing.", |  | ||||||
|             RemovedInDRF314Warning, stacklevel=2 |  | ||||||
|         ) |  | ||||||
| 
 |  | ||||||
|         assert 'allow_null' not in kwargs, '`allow_null` is not a valid option.' |  | ||||||
|         kwargs['allow_null'] = True |  | ||||||
| 
 |  | ||||||
|         super().__init__(**kwargs) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| # String types... | # String types... | ||||||
| 
 | 
 | ||||||
| class CharField(Field): | class CharField(Field): | ||||||
|  |  | ||||||
|  | @ -36,7 +36,6 @@ class SimpleMetadata(BaseMetadata): | ||||||
|     label_lookup = ClassLookupDict({ |     label_lookup = ClassLookupDict({ | ||||||
|         serializers.Field: 'field', |         serializers.Field: 'field', | ||||||
|         serializers.BooleanField: 'boolean', |         serializers.BooleanField: 'boolean', | ||||||
|         serializers.NullBooleanField: 'boolean', |  | ||||||
|         serializers.CharField: 'string', |         serializers.CharField: 'string', | ||||||
|         serializers.UUIDField: 'string', |         serializers.UUIDField: 'string', | ||||||
|         serializers.URLField: 'url', |         serializers.URLField: 'url', | ||||||
|  |  | ||||||
|  | @ -13,7 +13,7 @@ from django.db import models | ||||||
| from django.utils.encoding import force_str | from django.utils.encoding import force_str | ||||||
| 
 | 
 | ||||||
| from rest_framework import ( | from rest_framework import ( | ||||||
|     RemovedInDRF314Warning, exceptions, renderers, serializers |     RemovedInDRF315Warning, exceptions, renderers, serializers | ||||||
| ) | ) | ||||||
| from rest_framework.compat import uritemplate | from rest_framework.compat import uritemplate | ||||||
| from rest_framework.fields import _UnvalidatedField, empty | from rest_framework.fields import _UnvalidatedField, empty | ||||||
|  | @ -713,106 +713,10 @@ class AutoSchema(ViewInspector): | ||||||
| 
 | 
 | ||||||
|         return [path.split('/')[0].replace('_', '-')] |         return [path.split('/')[0].replace('_', '-')] | ||||||
| 
 | 
 | ||||||
|     def _get_path_parameters(self, path, method): |  | ||||||
|         warnings.warn( |  | ||||||
|             "Method `_get_path_parameters()` has been renamed to `get_path_parameters()`. " |  | ||||||
|             "The old name will be removed in DRF v3.14.", |  | ||||||
|             RemovedInDRF314Warning, stacklevel=2 |  | ||||||
|         ) |  | ||||||
|         return self.get_path_parameters(path, method) |  | ||||||
| 
 |  | ||||||
|     def _get_filter_parameters(self, path, method): |  | ||||||
|         warnings.warn( |  | ||||||
|             "Method `_get_filter_parameters()` has been renamed to `get_filter_parameters()`. " |  | ||||||
|             "The old name will be removed in DRF v3.14.", |  | ||||||
|             RemovedInDRF314Warning, stacklevel=2 |  | ||||||
|         ) |  | ||||||
|         return self.get_filter_parameters(path, method) |  | ||||||
| 
 |  | ||||||
|     def _get_responses(self, path, method): |  | ||||||
|         warnings.warn( |  | ||||||
|             "Method `_get_responses()` has been renamed to `get_responses()`. " |  | ||||||
|             "The old name will be removed in DRF v3.14.", |  | ||||||
|             RemovedInDRF314Warning, stacklevel=2 |  | ||||||
|         ) |  | ||||||
|         return self.get_responses(path, method) |  | ||||||
| 
 |  | ||||||
|     def _get_request_body(self, path, method): |  | ||||||
|         warnings.warn( |  | ||||||
|             "Method `_get_request_body()` has been renamed to `get_request_body()`. " |  | ||||||
|             "The old name will be removed in DRF v3.14.", |  | ||||||
|             RemovedInDRF314Warning, stacklevel=2 |  | ||||||
|         ) |  | ||||||
|         return self.get_request_body(path, method) |  | ||||||
| 
 |  | ||||||
|     def _get_serializer(self, path, method): |  | ||||||
|         warnings.warn( |  | ||||||
|             "Method `_get_serializer()` has been renamed to `get_serializer()`. " |  | ||||||
|             "The old name will be removed in DRF v3.14.", |  | ||||||
|             RemovedInDRF314Warning, stacklevel=2 |  | ||||||
|         ) |  | ||||||
|         return self.get_serializer(path, method) |  | ||||||
| 
 |  | ||||||
|     def _get_paginator(self): |  | ||||||
|         warnings.warn( |  | ||||||
|             "Method `_get_paginator()` has been renamed to `get_paginator()`. " |  | ||||||
|             "The old name will be removed in DRF v3.14.", |  | ||||||
|             RemovedInDRF314Warning, stacklevel=2 |  | ||||||
|         ) |  | ||||||
|         return self.get_paginator() |  | ||||||
| 
 |  | ||||||
|     def _map_field_validators(self, field, schema): |  | ||||||
|         warnings.warn( |  | ||||||
|             "Method `_map_field_validators()` has been renamed to `map_field_validators()`. " |  | ||||||
|             "The old name will be removed in DRF v3.14.", |  | ||||||
|             RemovedInDRF314Warning, stacklevel=2 |  | ||||||
|         ) |  | ||||||
|         return self.map_field_validators(field, schema) |  | ||||||
| 
 |  | ||||||
|     def _map_serializer(self, serializer): |  | ||||||
|         warnings.warn( |  | ||||||
|             "Method `_map_serializer()` has been renamed to `map_serializer()`. " |  | ||||||
|             "The old name will be removed in DRF v3.14.", |  | ||||||
|             RemovedInDRF314Warning, stacklevel=2 |  | ||||||
|         ) |  | ||||||
|         return self.map_serializer(serializer) |  | ||||||
| 
 |  | ||||||
|     def _map_field(self, field): |  | ||||||
|         warnings.warn( |  | ||||||
|             "Method `_map_field()` has been renamed to `map_field()`. " |  | ||||||
|             "The old name will be removed in DRF v3.14.", |  | ||||||
|             RemovedInDRF314Warning, stacklevel=2 |  | ||||||
|         ) |  | ||||||
|         return self.map_field(field) |  | ||||||
| 
 |  | ||||||
|     def _map_choicefield(self, field): |  | ||||||
|         warnings.warn( |  | ||||||
|             "Method `_map_choicefield()` has been renamed to `map_choicefield()`. " |  | ||||||
|             "The old name will be removed in DRF v3.14.", |  | ||||||
|             RemovedInDRF314Warning, stacklevel=2 |  | ||||||
|         ) |  | ||||||
|         return self.map_choicefield(field) |  | ||||||
| 
 |  | ||||||
|     def _get_pagination_parameters(self, path, method): |  | ||||||
|         warnings.warn( |  | ||||||
|             "Method `_get_pagination_parameters()` has been renamed to `get_pagination_parameters()`. " |  | ||||||
|             "The old name will be removed in DRF v3.14.", |  | ||||||
|             RemovedInDRF314Warning, stacklevel=2 |  | ||||||
|         ) |  | ||||||
|         return self.get_pagination_parameters(path, method) |  | ||||||
| 
 |  | ||||||
|     def _allows_filters(self, path, method): |  | ||||||
|         warnings.warn( |  | ||||||
|             "Method `_allows_filters()` has been renamed to `allows_filters()`. " |  | ||||||
|             "The old name will be removed in DRF v3.14.", |  | ||||||
|             RemovedInDRF314Warning, stacklevel=2 |  | ||||||
|         ) |  | ||||||
|         return self.allows_filters(path, method) |  | ||||||
| 
 |  | ||||||
|     def _get_reference(self, serializer): |     def _get_reference(self, serializer): | ||||||
|         warnings.warn( |         warnings.warn( | ||||||
|             "Method `_get_reference()` has been renamed to `get_reference()`. " |             "Method `_get_reference()` has been renamed to `get_reference()`. " | ||||||
|             "The old name will be removed in DRF v3.14.", |             "The old name will be removed in DRF v3.15.", | ||||||
|             RemovedInDRF314Warning, stacklevel=2 |             RemovedInDRF315Warning, stacklevel=2 | ||||||
|         ) |         ) | ||||||
|         return self.get_reference(serializer) |         return self.get_reference(serializer) | ||||||
|  |  | ||||||
|  | @ -52,7 +52,7 @@ from rest_framework.fields import (  # NOQA # isort:skip | ||||||
|     BooleanField, CharField, ChoiceField, DateField, DateTimeField, DecimalField, |     BooleanField, CharField, ChoiceField, DateField, DateTimeField, DecimalField, | ||||||
|     DictField, DurationField, EmailField, Field, FileField, FilePathField, FloatField, |     DictField, DurationField, EmailField, Field, FileField, FilePathField, FloatField, | ||||||
|     HiddenField, HStoreField, IPAddressField, ImageField, IntegerField, JSONField, |     HiddenField, HStoreField, IPAddressField, ImageField, IntegerField, JSONField, | ||||||
|     ListField, ModelField, MultipleChoiceField, NullBooleanField, ReadOnlyField, |     ListField, ModelField, MultipleChoiceField, ReadOnlyField, | ||||||
|     RegexField, SerializerMethodField, SlugField, TimeField, URLField, UUIDField, |     RegexField, SerializerMethodField, SlugField, TimeField, URLField, UUIDField, | ||||||
| ) | ) | ||||||
| from rest_framework.relations import (  # NOQA # isort:skip | from rest_framework.relations import (  # NOQA # isort:skip | ||||||
|  |  | ||||||
|  | @ -679,9 +679,9 @@ class TestBooleanField(FieldValues): | ||||||
|             assert exc_info.value.detail == expected |             assert exc_info.value.detail == expected | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class TestNullBooleanField(TestBooleanField): | class TestNullableBooleanField(TestBooleanField): | ||||||
|     """ |     """ | ||||||
|     Valid and invalid values for `NullBooleanField`. |     Valid and invalid values for `BooleanField` when `allow_null=True`. | ||||||
|     """ |     """ | ||||||
|     valid_inputs = { |     valid_inputs = { | ||||||
|         'true': True, |         'true': True, | ||||||
|  | @ -706,16 +706,6 @@ class TestNullBooleanField(TestBooleanField): | ||||||
|     field = serializers.BooleanField(allow_null=True) |     field = serializers.BooleanField(allow_null=True) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class TestNullableBooleanField(TestNullBooleanField): |  | ||||||
|     """ |  | ||||||
|     Valid and invalid values for `BooleanField` when `allow_null=True`. |  | ||||||
|     """ |  | ||||||
| 
 |  | ||||||
|     @property |  | ||||||
|     def field(self): |  | ||||||
|         return serializers.BooleanField(allow_null=True) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| # String types... | # String types... | ||||||
| 
 | 
 | ||||||
| class TestCharField(FieldValues): | class TestCharField(FieldValues): | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user