You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 4a92b5f
Browse filesBrowse the repository at this point in the historyBrowse files
Copy file name to clipboardExpand all lines: docs/api-guide/fields.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -63,7 +63,7 @@ For example:
63
63
64
64
When serializing the instance, default will be used if the object attribute or dictionary key is not present in the instance.
65
65
66
-
Note that setting a `default` value implies that the field is not required. Including both the `default`and`required` keyword arguments is invalid and will raise an error.
66
+
Note that setting a `default` value implies that the field is not required. Combining `default`with`required=True`is invalid and will raise an error. An explicit `required=False` alongside `default` is allowed, but redundant.
Copy file name to clipboardExpand all lines: docs/api-guide/pagination.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -369,7 +369,7 @@ The [`DRF-extensions` package][drf-extensions] includes a [`PaginateByMaxMixin`
369
369
370
370
### drf-proxy-pagination
371
371
372
-
The [`drf-proxy-pagination` package][drf-proxy-pagination] includes a `ProxyPagination` class which allows to choose pagination class with a query parameter.
372
+
The [`drf-proxy-pagination` package][drf-proxy-pagination] includes a `ProxyPagination` class which allows choosing the pagination class with a query parameter.
Copy file name to clipboardExpand all lines: docs/api-guide/serializers.md
+31-3Lines changed: 31 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -159,7 +159,9 @@ When deserializing data, you always need to call `is_valid()` before attempting
159
159
160
160
Each key in the dictionary will be the field name, and the values will be lists of strings of any error messages corresponding to that field. The `non_field_errors` key may also be present, and will list any general validation errors. The name of the `non_field_errors` key may be customized using the `NON_FIELD_ERRORS_KEY` REST framework setting.
161
161
162
-
When deserializing a list of items, errors will be returned as a list of dictionaries representing each of the deserialized items.
162
+
When deserializing a list of items, errors are returned as a dictionary keyed by the indexes of invalid items. Valid items are omitted from the dictionary.
163
+
164
+
To temporarily use the list-based format from versions before REST framework 3.18, set `LIST_SERIALIZER_ERRORS_AS_DICT` to `False`. This format includes an empty dictionary for each valid item and is deprecated. It will be removed in REST framework 3.20.
163
165
164
166
#### Raising an exception on invalid data
165
167
@@ -559,6 +561,8 @@ This option should be a list or tuple of field names, and is declared as follows
559
561
560
562
Model fields which have `editable=False` set, and `AutoField` fields will be set to read-only by default, and do not need to be added to the `read_only_fields` option.
561
563
564
+
Please keep in mind that, if a field has already been explicitly declared on the serializer class (or a parent class), then the `read_only_fields` option will not apply to that field. Set `read_only=True` on the field itself instead.
565
+
562
566
!!! note
563
567
There is a special-case where a read-only field is part of a `unique_together` constraint at the model level. In this case the field is required by the serializer class in order to validate the constraint, but should also not be editable by the user.
564
568
@@ -591,7 +595,7 @@ This option is a dictionary, mapping field names to a dictionary of keyword argu
591
595
user.save()
592
596
return user
593
597
594
-
Please keep in mind that, if the field has already been explicitly declared on the serializer class, then the `extra_kwargs` option will be ignored.
598
+
Please keep in mind that, if the field has already been explicitly declared on the serializer class, then the `extra_kwargs` option will be ignored. The same is true of `read_only_fields`, which is implemented using `extra_kwargs`.
595
599
596
600
### Relational fields
597
601
@@ -852,6 +856,30 @@ Here's an example of how you might choose to implement multiple updates:
852
856
class Meta:
853
857
list_serializer_class = BookListSerializer
854
858
859
+
If the child serializer includes uniqueness validators (`UniqueValidator`, `UniqueTogetherValidator`, or the
860
+
`UniqueForDateValidator` family), they need to know which object each item in the list is updating, so
861
+
that the object itself is not reported as a uniqueness conflict. By default the child serializer's
862
+
`.instance` is the whole queryset or list that was passed to the list serializer, so these validators will
863
+
raise a `RuntimeError` during a multiple update. To support this, override `run_child_validation()` on
864
+
your `ListSerializer` subclass to set the child's `.instance` and `.initial_data` for each item before
865
+
validation. For example, if `self.instance` is a queryset:
866
+
867
+
class BookListSerializer(serializers.ListSerializer):
868
+
def run_child_validation(self, data):
869
+
# `.instance` stays `None` for items that do not exist yet, and
870
+
# for malformed items, which child validation will then reject
When a serializer with `many=True` is instantiated, we need to determine which arguments and keyword arguments should be passed to the `.__init__()` method for both the child `Serializer` class, and for the parent `ListSerializer` class.
@@ -1190,7 +1218,7 @@ The [html-json-forms][html-json-forms] package provides an algorithm and seriali
1190
1218
1191
1219
### DRF Writable Nested
1192
1220
1193
-
The [drf-writable-nested][drf-writable-nested] package provides writable nested model serializer which allows to create/update models with nested related data.
1221
+
The [drf-writable-nested][drf-writable-nested] package provides writable nested model serializer which allows creating/updating models with nested related data.
Copy file name to clipboardExpand all lines: docs/api-guide/settings.md
+10Lines changed: 10 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -462,6 +462,16 @@ A string representing the key that should be used for serializer errors that do
462
462
463
463
Default: `'non_field_errors'`
464
464
465
+
#### LIST_SERIALIZER_ERRORS_AS_DICT
466
+
467
+
Controls the format of per-item validation errors produced by `ListSerializer`, including serializers instantiated with `many=True`.
468
+
469
+
When set to `True`, errors are returned as a dictionary keyed by the indexes of invalid items. Valid items are omitted from the dictionary. This format was introduced in REST framework 3.18.0.
470
+
471
+
When set to `False`, errors are returned in the list-based format used before REST framework 3.18, with one entry for each input item and an empty dictionary for each valid item. This format is deprecated and will be removed in REST framework 3.20.
472
+
473
+
Default: `True`
474
+
465
475
#### URL_FIELD_NAME
466
476
467
477
A string representing the key that should be used for the URL fields generated by `HyperlinkedModelSerializer`.
Copy file name to clipboardExpand all lines: docs/api-guide/validators.md
+23-1Lines changed: 23 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -102,7 +102,7 @@ The validator should be applied to *serializer classes*, like so:
102
102
]
103
103
104
104
!!! note
105
-
The `UniqueTogetherValidator` class always imposes an implicit constraint that all the fields it applies to are always treated as required. Fields with `default` values are an exception to this as they always supply a value even when omitted from user input.
105
+
The `UniqueTogetherValidator` class always imposes an implicit constraint that all the fields it applies to are always treated as required. Fields with `default` values are an exception to this as they always supply a value even when omitted from user input. When using `ModelSerializer`, model fields with `null=True` default to `None`, and `CharField` or `TextField` model fields with `blank=True` default to an empty string, so these are not treated as required either.
106
106
107
107
## UniqueForDateValidator
108
108
@@ -222,6 +222,28 @@ For example:
222
222
extra_kwargs = {'client': {'required': False}}
223
223
validators = [] # Remove a default "unique together" constraint.
224
224
225
+
### UniqueConstraint with conditions
226
+
227
+
When using Django's `UniqueConstraint` with conditions that reference other model fields, DRF will automatically use
228
+
`UniqueTogetherValidator` instead of field-level `UniqueValidator`. This ensures proper validation behavior when the constraint
229
+
effectively involves multiple fields.
230
+
231
+
For example, a single-field constraint with a condition becomes a multi-field validation when the condition references other fields.
232
+
233
+
class MyModel(models.Model):
234
+
name = models.CharField(max_length=100)
235
+
status = models.CharField(max_length=20)
236
+
237
+
class Meta:
238
+
constraints = [
239
+
models.UniqueConstraint(
240
+
fields=['name'],
241
+
condition=models.Q(status='active'),
242
+
name='unique_active_name'
243
+
)
244
+
]
245
+
246
+
225
247
### Updating nested serializers
226
248
227
249
When applying an update to an existing instance, uniqueness validators will
Copy file name to clipboardExpand all lines: docs/community/contributing.md
+47Lines changed: 47 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -160,6 +160,52 @@ Once you've made a pull request take a look at the build status in the GitHub in
160
160
161
161
Sometimes, in order to ensure your code works on various different versions of Django, Python or third party libraries, you'll need to run slightly different code depending on the environment. Any code that branches in this way should be isolated into the `compat.py` module, and should provide a single common interface that the rest of the codebase can use.
162
162
163
+
### Deprecating a feature
164
+
165
+
REST framework follows a formal [deprecation policy][deprecation-policy]: a feature deprecated during the development of `3.X` keeps working until `3.X+2` removes it. In practice this means that a pull request that deprecates something should not change any behavior, only warn about the change to come.
166
+
167
+
The warning classes live in `rest_framework/deprecation.py`, and are named after the release that removes the feature. For example, during the development of 3.0 you'll find:
168
+
169
+
*`RemovedInDRF31Warning`, a `DeprecationWarning`, aliased as `RemovedInNextDRFVersionWarning`. Features flagged with it were deprecated one cycle ago, and are removed in the next release.
170
+
*`RemovedInDRF32Warning`, a `PendingDeprecationWarning`, aliased as `RemovedAfterNextDRFVersionWarning`. This is the class **new deprecations** should use.
171
+
172
+
To deprecate a feature:
173
+
174
+
1. Keep the existing behavior working, and raise the pending deprecation warning from the deprecated code path. Refer to the warning class by its concrete name rather than the alias, so that it's easy to grep for everything that has to go when the removal comes around.
175
+
176
+
```python
177
+
import warnings
178
+
179
+
from rest_framework.deprecation import RemovedInDRF32Warning
180
+
181
+
warnings.warn(
182
+
"The `foo` argument is deprecated and will be removed in DRF 3.2. "
183
+
"Use `bar` instead.",
184
+
RemovedInDRF32Warning,
185
+
stacklevel=2,
186
+
)
187
+
```
188
+
189
+
The message should say what is deprecated, which release removes it, and what to use instead. Pick a `stacklevel` that points the warning at the user's code rather than at REST framework internals.
190
+
191
+
2. If the deprecation can be worked around ahead of time, consider adding a setting that opts into the new behavior early, and mention it in the warning message.
192
+
193
+
3. Add a test asserting that the warning is raised, and update the existing tests of the old behavior to expect it:
194
+
195
+
```python
196
+
with pytest.warns(RemovedInDRF32Warning, match="Use `bar` instead"):
197
+
...
198
+
```
199
+
200
+
4. Update the documentation for the feature, flagging the deprecation with an admonition:
201
+
202
+
```
203
+
!!! warning
204
+
The `foo` argument is deprecated and will be removed inDRF3.2. Use `bar` instead.
205
+
```
206
+
207
+
Removing a deprecated feature is the mirror image, and happens as part of the release process. When 3.1is released, everything raising a `RemovedInDRF31Warning`is deleted, along with the class itself and the documentation of the deprecated behavior, `RemovedInDRF32Warning`is escalated to subclass `DeprecationWarning`, a fresh `RemovedInDRF33Warning`is added for the next cycle's deprecations, and the two aliases are moved on to point at them.
208
+
163
209
## Documentation
164
210
165
211
The documentation forREST framework is built from the [Markdown][markdown] source files in [the docs directory][docs].
@@ -244,3 +290,4 @@ The documentation theme styles `info`, `warning`, `tip` and `danger` admonition
Copy file name to clipboardExpand all lines: docs/community/project-management.md
+2-1Lines changed: 2 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -58,7 +58,8 @@ Our PyPI releases is automated in GitHub actions on tag pushes. The following te
58
58
-`pyproject.toml` Python & Django version trove classifiers
59
59
-`README` Python & Django versions
60
60
-`docs` Python & Django versions
61
-
- Ensure the pull request increments the version to `*.*.*` in [`restframework/__init__.py`](https://github.com/encode/django-rest-framework/blob/main/rest_framework/__init__.py).
61
+
- Ensure the pull request increments the version to `*.*.*` in [`rest_framework/__init__.py`](https://github.com/encode/django-rest-framework/blob/main/rest_framework/__init__.py).
62
+
- Ensure the deprecation warnings in [`rest_framework/deprecation.py`](https://github.com/encode/django-rest-framework/blob/main/rest_framework/deprecation.py) have been rotated for the release, following the [deprecation policy](release-notes.md#deprecation-policy).
Copy file name to clipboardExpand all lines: docs/community/release-notes.md
+46Lines changed: 46 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -22,8 +22,29 @@ The timeline for deprecation of a feature present in version 1.0 would work as f
22
22
23
23
* Version 1.3 would remove the deprecated bits of API entirely.
24
24
25
+
Two aliases always point at the warning classes for the current release cycle, so you can refer to them without updating your configuration on every release:
26
+
27
+
*`RemovedInNextDRFVersionWarning` — features that the next feature release removes. Always a `DeprecationWarning`.
28
+
*`RemovedAfterNextDRFVersionWarning` — features that the release after next removes. Always a `PendingDeprecationWarning`.
29
+
25
30
Note that in line with Django's policy, any parts of the framework not mentioned in the documentation should generally be considered private API, and may be subject to change.
26
31
32
+
### Surfacing deprecations in your test suite
33
+
34
+
Deprecations are much easier to deal with one release at a time, so it's worth failing your test suite on anything that is due to be removed in the next release, while keeping the earlier warnings visible.
35
+
36
+
If you run your tests with pytest, add the following to your `pyproject.toml`:
When a warning does fire, the message names the release that removes the feature and what to use instead. Once you have dealt with them all, drop the `always` filter down to `error` too, and you'll be ready for the release after next as well.
47
+
27
48
## Upgrading
28
49
29
50
To upgrade Django REST framework to the latest version, use pip:
@@ -38,6 +59,31 @@ You can determine your currently installed version using `pip show`:
38
59
39
60
## 3.18.x series
40
61
62
+
### 3.18.1
63
+
64
+
**Date**: 7th September 2026
65
+
66
+
#### Bug fixes
67
+
68
+
* Fix duplicate validation errors for GenericIPAddressField with protocol by [@browniebroke](https://github.com/browniebroke) in [#10011](https://github.com/encode/django-rest-framework/pull/10011)
69
+
* Fix int64 format detection for negative `IntegerField` minimums in OpenAPI schema definition by [@zainnadeem786](https://github.com/zainnadeem786) in [#9989](https://github.com/encode/django-rest-framework/pull/9989)
70
+
* Fix list serializer on unique constraint validator by [@MehrazRumman](https://github.com/MehrazRumman) in [#10033](https://github.com/encode/django-rest-framework/pull/10033)
71
+
* Reject non-finite values (nan, inf) in FloatField by [@winklemad](https://github.com/winklemad) in [#9998](https://github.com/encode/django-rest-framework/pull/9998)
72
+
73
+
#### Other changes
74
+
75
+
* Add a compatibility setting for `ListSerializer` error formats by [@Kub-AT](https://github.com/Kub-AT) in [#10027](https://github.com/encode/django-rest-framework/pull/10027)
76
+
* Expand deprecation classes and review deprecation policy by [@browniebroke](https://github.com/browniebroke) in [#10034](https://github.com/encode/django-rest-framework/pull/10034)
77
+
78
+
#### New Contributors
79
+
80
+
*[@abidaliamanat9](https://github.com/abidaliamanat9) made their first contribution in [#10028](https://github.com/encode/django-rest-framework/pull/10028)
81
+
*[@epuronta](https://github.com/epuronta) made their first contribution in [#10030](https://github.com/encode/django-rest-framework/pull/10030)
82
+
*[@Kub-AT](https://github.com/Kub-AT) made their first contribution in [#10027](https://github.com/encode/django-rest-framework/pull/10027)
83
+
*[@winklemad](https://github.com/winklemad) made their first contribution in [#9998](https://github.com/encode/django-rest-framework/pull/9998)
0 commit comments