Skip to content

Commit 6521fc9

Browse files
authored
Merge branch 'main' into fix/nulls-distinct-validator-8409
2 parents 33820f1 + 65aa4b8 commit 6521fc9

64 files changed

Lines changed: 403 additions & 7167 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/dependabot.yml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,6 @@ updates:
3232

3333
optional:
3434
patterns:
35-
- "coreapi"
36-
- "coreschema"
3735
- "django-filter"
3836
- "django-guardian"
3937
- "inflection"

.github/workflows/release.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ env:
2323
jobs:
2424
build:
2525
name: Build distribution 📦
26+
if: github.repository == 'encode/django-rest-framework'
2627
runs-on: ubuntu-24.04
2728
steps:
2829
- uses: actions/checkout@v6

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,5 @@ coverage.*
1919
!.github
2020
!.gitignore
2121
!.pre-commit-config.yaml
22+
23+
.idea

docs/api-guide/testing.md

Lines changed: 9 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -265,48 +265,22 @@ For example...
265265

266266
### Live tests
267267

268-
With careful usage both the `RequestsClient` and the `CoreAPIClient` provide
269-
the ability to write test cases that can run either in development, or be run
270-
directly against your staging server or production environment.
271-
268+
With careful usage the `RequestsClient` provides the ability to write tests
269+
that exercise your API views in a more end-to-end fashion than `APIClient`,
270+
while still running entirely in-process against your local Django application.
271+
272+
Note that `RequestsClient` mounts a WSGI adapter and does not perform real
273+
network I/O. It cannot be used to send HTTP requests to remote services such
274+
as staging or production servers. For live tests against a deployed service,
275+
you should instead use a plain `requests.Session` (or similar HTTP client)
276+
configured with the appropriate base URL and authentication.
272277
Using this style to create basic tests of a few core pieces of functionality is
273278
a powerful way to validate your live service. Doing so may require some careful
274279
attention to setup and teardown to ensure that the tests run in a way that they
275280
do not directly affect customer data.
276281

277282
---
278283

279-
## CoreAPIClient
280-
281-
The CoreAPIClient allows you to interact with your API using the Python
282-
`coreapi` client library.
283-
284-
# Fetch the API schema
285-
client = CoreAPIClient()
286-
schema = client.get('http://testserver/schema/')
287-
288-
# Create a new organization
289-
params = {'name': 'MegaCorp', 'status': 'active'}
290-
client.action(schema, ['organizations', 'create'], params)
291-
292-
# Ensure that the organization exists in the listing
293-
data = client.action(schema, ['organizations', 'list'])
294-
assert(len(data) == 1)
295-
assert(data == [{'name': 'MegaCorp', 'status': 'active'}])
296-
297-
### Headers & Authentication
298-
299-
Custom headers and authentication may be used with `CoreAPIClient` in a
300-
similar way as with `RequestsClient`.
301-
302-
from requests.auth import HTTPBasicAuth
303-
304-
client = CoreAPIClient()
305-
client.session.auth = HTTPBasicAuth('user', 'pass')
306-
client.session.headers.update({'x-test': 'true'})
307-
308-
---
309-
310284
## API Test cases
311285

312286
REST framework includes the following test case classes, that mirror the existing [Django's test case classes][provided_test_case_classes], but use `APIClient` instead of Django's default `Client`.

docs/api-guide/views.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -202,16 +202,16 @@ decorator. For example:
202202
from rest_framework.schemas import AutoSchema
203203

204204
class CustomAutoSchema(AutoSchema):
205-
def get_link(self, path, method, base_url):
205+
def get_operation(self, path, method):
206206
# override view introspection here...
207207

208208
@api_view(['GET'])
209209
@schema(CustomAutoSchema())
210210
def view(request):
211211
return Response({"message": "Hello for today! See you tomorrow!"})
212212

213-
This decorator takes a single `AutoSchema` instance, an `AutoSchema` subclass
214-
instance or `ManualSchema` instance as described in the [Schemas documentation][schemas].
213+
This decorator takes a single `AutoSchema` instance or an `AutoSchema` subclass
214+
instance as described in the [Schemas documentation][schemas].
215215
You may pass `None` in order to exclude the view from schema generation.
216216

217217
@api_view(['GET'])

docs/community/project-management.md

Lines changed: 27 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -40,48 +40,36 @@ Further notes for maintainers:
4040

4141
## Release process
4242

43-
* The release manager is selected by `@tomchristie`.
43+
* The release manager is selected.
4444
* The release manager will then have the maintainer role added to PyPI package.
4545
* The previous manager will then have the maintainer role removed from the PyPI package.
4646

47-
Our PyPI releases will be handled by either the current release manager, or by `@tomchristie`. Every release should have an open issue tagged with the `Release` label and marked against the appropriate milestone.
48-
49-
The following template should be used for the description of the issue, and serves as a release checklist.
50-
51-
Release manager is @***.
52-
Pull request is #***.
53-
54-
Checklist:
55-
56-
- [ ] Create pull request for [release notes](https://github.com/encode/django-rest-framework/blob/mains/docs/topics/release-notes.md) based on the [*.*.* milestone](https://github.com/encode/django-rest-framework/milestones/***).
57-
- [ ] Update supported versions:
58-
- [ ] `pyproject.toml` `python_requires` list
59-
- [ ] `pyproject.toml` Python & Django version trove classifiers
60-
- [ ] `README` Python & Django versions
61-
- [ ] `docs` Python & Django versions
62-
- [ ] 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).
63-
- [ ] Update the release-notes.md:
64-
- Start drafting a new release in GitHub: https://github.com/encode/django-rest-framework/releases/new
65-
- Select the tag that you want to give to the next release and the previous tag
66-
- Click the "Generate release notes" button
67-
- Don't confirm anything yet! Copy the generated content to a file `input.md`
68-
- Run `uv tool run linkify-gh-markdown input.md` to make the links absolute
69-
- Put the generated content in the release-notes.md file
70-
- [ ] Ensure documentation validates
71-
- Build and serve docs `mkdocs serve`
72-
- Validate links `pylinkvalidate.py -P http://127.0.0.1:8000`
73-
- [ ] Confirm with other maintainers that the release is finalized and ready to go.
74-
- [ ] Ensure that release date is included in pull request.
75-
- [ ] Merge the release pull request.
76-
- [ ] Tag the release, either with `git tag -a *.*.* -m 'version *.*.*'; git push --tags` or in GitHub.
77-
- [ ] Wait for the release workflow to run. It will build the distribution, upload it to Test PyPI, PyPI and create the GitHub release.
78-
- [ ] Make a release announcement on the [discussion group](https://groups.google.com/forum/?fromgroups#!forum/django-rest-framework).
79-
- [ ] Make a release announcement on social media (Mastodon, etc...) and on the [Django forum](https://forum.djangoproject.com/).
80-
- [ ] Close the milestone on GitHub.
81-
82-
To modify this process for future releases make a pull request to the [project management](https://www.django-rest-framework.org/topics/project-management/) documentation.
83-
84-
When pushing the release to PyPI ensure that your environment has been installed from our development `requirement.txt`, so that documentation and PyPI installs are consistently being built against a pinned set of packages.
47+
Our PyPI releases is automated in GitHub actions on tag pushes. The following template can be used as a release checklist:
48+
49+
- Create pull request for [release notes](https://github.com/encode/django-rest-framework/blob/mains/docs/topics/release-notes.md):
50+
- Start drafting a [new release in GitHub](https://github.com/encode/django-rest-framework/releases/new)
51+
- Select the tag that you want to give to the release and the previous tag
52+
- Click the "Generate release notes" button
53+
- Don't confirm anything! Copy the generated content to a file `input.md`
54+
- Run `uv tool run linkify-gh-markdown input.md` to make the links absolute
55+
- Put the generated content in the `release-notes.md` file
56+
- Update supported versions:
57+
- `pyproject.toml` ensure the `requires-python` key is up to date
58+
- `pyproject.toml` Python & Django version trove classifiers
59+
- `README` Python & Django versions
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).
62+
- Ensure documentation validates
63+
- Build and serve docs `mkdocs serve`
64+
- Validate links `pylinkvalidate.py -P http://127.0.0.1:8000`
65+
- Confirm with other maintainers that the release is finalized and ready to go.
66+
- Ensure that release date is included in pull request.
67+
- Merge the release pull request.
68+
- Tag the release, either with `git tag -a *.*.* -m 'version *.*.*'; git push --tags` or in GitHub.
69+
- Wait for the release workflow to run. It will build the distribution, upload it to Test PyPI, PyPI and create the GitHub release.
70+
- Make a release announcement on the [discussion group](https://groups.google.com/forum/?fromgroups#!forum/django-rest-framework).
71+
- Make a release announcement on social media (Mastodon, etc...) and on the [Django forum](https://forum.djangoproject.com/).
72+
- Close the milestone on GitHub.
8573

8674
---
8775

docs/community/release-notes.md

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,105 @@ You can determine your currently installed version using `pip show`:
3636

3737
---
3838

39+
## 3.17.x series
40+
41+
### 3.17.1
42+
43+
**Date**: 24th March 2026
44+
45+
#### Bug fixes
46+
47+
* Fix `HTMLFormRenderer` with empty `datetime` values by [@p-r-a-v-i-n](https://github.com/p-r-a-v-i-n) in [#9928](https://github.com/encode/django-rest-framework/pull/9928)
48+
49+
**Full Changelog**: [3.17.0...3.17.1](https://github.com/encode/django-rest-framework/compare/3.17.0...3.17.1)
50+
51+
### 3.17.0
52+
53+
**Date**: 18th March 2026
54+
55+
#### Breaking changes
56+
57+
* Drop support for Python 3.9 by [@auvipy](https://github.com/auvipy) in [#9781](https://github.com/encode/django-rest-framework/pull/9781)
58+
* Drop deprecated coreapi support by [@browniebroke](https://github.com/browniebroke) in [#9895](https://github.com/encode/django-rest-framework/pull/9895)
59+
60+
#### Features
61+
62+
* Add Django 6.0 support by [@MehrazRumman](https://github.com/MehrazRumman) in [#9819](https://github.com/encode/django-rest-framework/pull/9819)
63+
* Add support for Python 3.14 by [@cclauss](https://github.com/cclauss) in [#9780](https://github.com/encode/django-rest-framework/pull/9780)
64+
* Add ability to specify output format for `DurationField` by [@sevdog](https://github.com/sevdog) in [#8532](https://github.com/encode/django-rest-framework/pull/8532)
65+
* Add missing decorators: `@versioning_class()`, `@content_negotiation_class()`, `@metadata_class()` for function-based views by [@qqii](https://github.com/qqii) in [#9719](https://github.com/encode/django-rest-framework/pull/9719)
66+
* Support `violation_error_code` and `violation_error_message` from `UniqueConstraint` in `UniqueTogetherValidator` by [@s-aleshin](https://github.com/s-aleshin) in [#9766](https://github.com/encode/django-rest-framework/pull/9766)
67+
* Add support for `ipaddress` objects in `JSONEncoder` by [@corenting](https://github.com/corenting) in [#9087](https://github.com/encode/django-rest-framework/pull/9087)
68+
* Add optional support to serialize `BigInteger` to string by [@HoodyH](https://github.com/HoodyH) in [#9775](https://github.com/encode/django-rest-framework/pull/9775)
69+
70+
#### Bug fixes
71+
72+
* Prevent small risk of `Token` overwrite by [@mahdirahimi1999](https://github.com/mahdirahimi1999) in [#9754](https://github.com/encode/django-rest-framework/pull/9754)
73+
* Fix `UniqueTogetherValidator` validation when condition references a read-only field by [@ticosax](https://github.com/ticosax) in [#9764](https://github.com/encode/django-rest-framework/pull/9764)
74+
* Fix validation on many to many field when `default=None` by [@Genarito](https://github.com/Genarito) in [#9790](https://github.com/encode/django-rest-framework/pull/9790)
75+
* Fix invalid SPDX license expression in `__init__.py` by [@TheFunctionalGuy](https://github.com/TheFunctionalGuy) in [#9799](https://github.com/encode/django-rest-framework/pull/9799)
76+
* Fix `HTMLFormRenderer` to ensure a valid `datetime-local` format by [@mgaligniana](https://github.com/mgaligniana) in [#9365](https://github.com/encode/django-rest-framework/pull/9365)
77+
* Fix mutable default arguments in OrderingFilter methods by [@killerdevildog](https://github.com/killerdevildog) in [#9742](https://github.com/encode/django-rest-framework/pull/9742)
78+
* Update TokenAdmin to respect USERNAME_FIELD of the user model by [@m000](https://github.com/m000) in [#9836](https://github.com/encode/django-rest-framework/pull/9836)
79+
* Preserve ordering in `MultipleChoiceField` by [@fbozhang](https://github.com/fbozhang) in [#9735](https://github.com/encode/django-rest-framework/pull/9735)
80+
81+
#### Translations
82+
83+
* Update French translation by [@SebCorbin](https://github.com/SebCorbin) in [#9770](https://github.com/encode/django-rest-framework/pull/9770)
84+
* Update Brazilian Portuguese translations by [@JVPinheiroReis](https://github.com/JVPinheiroReis) in [#9828](https://github.com/encode/django-rest-framework/pull/9828)
85+
* Fix and improve French translations by [@deronnax](https://github.com/deronnax) in [#9896](https://github.com/encode/django-rest-framework/pull/9896)
86+
* Add missing Russian translation by [@minorytanaka](https://github.com/minorytanaka) in [#9903](https://github.com/encode/django-rest-framework/pull/9903)
87+
88+
#### Packaging
89+
90+
* Migrate packaging to `pyproject.toml` by [@deronnax](https://github.com/deronnax) in [#9056](https://github.com/encode/django-rest-framework/pull/9056)
91+
* Move package data rules from `MANIFEST.in` to `pyproject.toml` by [@p-r-a-v-i-n](https://github.com/p-r-a-v-i-n) in [#9825](https://github.com/encode/django-rest-framework/pull/9825)
92+
* Set up release workflow with trusted publisher by [@browniebroke](https://github.com/browniebroke) in [#9852](https://github.com/encode/django-rest-framework/pull/9852)
93+
94+
#### Other changes
95+
96+
* Refactor token generation to use the `secrets` module by [@mahdirahimi1999](https://github.com/mahdirahimi1999) in [#9760](https://github.com/encode/django-rest-framework/pull/9760)
97+
* Add validation for decorator out-of-order with `@api_view` by [@kernelshard](https://github.com/kernelshard) in [#9821](https://github.com/encode/django-rest-framework/pull/9821)
98+
* Switch to mkdocs material theme for documentation by [@browniebroke](https://github.com/browniebroke) in [#9849](https://github.com/encode/django-rest-framework/pull/9849)
99+
100+
#### New Contributors
101+
102+
* [@khaledsukkar2](https://github.com/khaledsukkar2) made their first contribution in [#9717](https://github.com/encode/django-rest-framework/pull/9717)
103+
* [@qqii](https://github.com/qqii) made their first contribution in [#9719](https://github.com/encode/django-rest-framework/pull/9719)
104+
* [@zankoAn](https://github.com/zankoAn) made their first contribution in [#9788](https://github.com/encode/django-rest-framework/pull/9788)
105+
* [@uche-wealth](https://github.com/uche-wealth) made their first contribution in [#9795](https://github.com/encode/django-rest-framework/pull/9795)
106+
* [@s-aleshin](https://github.com/s-aleshin) made their first contribution in [#9766](https://github.com/encode/django-rest-framework/pull/9766)
107+
* [@Infamous003](https://github.com/Infamous003) made their first contribution in [#9794](https://github.com/encode/django-rest-framework/pull/9794)
108+
* [@Genarito](https://github.com/Genarito) made their first contribution in [#9790](https://github.com/encode/django-rest-framework/pull/9790)
109+
* [@TheFunctionalGuy](https://github.com/TheFunctionalGuy) made their first contribution in [#9799](https://github.com/encode/django-rest-framework/pull/9799)
110+
* [@mahdighadiriii](https://github.com/mahdighadiriii) made their first contribution in [#9800](https://github.com/encode/django-rest-framework/pull/9800)
111+
* [@p-r-a-v-i-n](https://github.com/p-r-a-v-i-n) made their first contribution in [#9801](https://github.com/encode/django-rest-framework/pull/9801)
112+
* [@itssimon](https://github.com/itssimon) made their first contribution in [#9718](https://github.com/encode/django-rest-framework/pull/9718)
113+
* [@huynguyengl99](https://github.com/huynguyengl99) made their first contribution in [#9785](https://github.com/encode/django-rest-framework/pull/9785)
114+
* [@corenting](https://github.com/corenting) made their first contribution in [#9087](https://github.com/encode/django-rest-framework/pull/9087)
115+
* [@killerdevildog](https://github.com/killerdevildog) made their first contribution in [#9742](https://github.com/encode/django-rest-framework/pull/9742)
116+
* [@dayandavid](https://github.com/dayandavid) made their first contribution in [#9820](https://github.com/encode/django-rest-framework/pull/9820)
117+
* [@abhishektiwari](https://github.com/abhishektiwari) made their first contribution in [#9826](https://github.com/encode/django-rest-framework/pull/9826)
118+
* [@HoodyH](https://github.com/HoodyH) made their first contribution in [#9775](https://github.com/encode/django-rest-framework/pull/9775)
119+
* [@Shrikantgiri25](https://github.com/Shrikantgiri25) made their first contribution in [#9808](https://github.com/encode/django-rest-framework/pull/9808)
120+
* [@JVPinheiroReis](https://github.com/JVPinheiroReis) made their first contribution in [#9828](https://github.com/encode/django-rest-framework/pull/9828)
121+
* [@m000](https://github.com/m000) made their first contribution in [#9836](https://github.com/encode/django-rest-framework/pull/9836)
122+
* [@Nabute](https://github.com/Nabute) made their first contribution in [#9767](https://github.com/encode/django-rest-framework/pull/9767)
123+
* [@therealjozber](https://github.com/therealjozber) made their first contribution in [#9845](https://github.com/encode/django-rest-framework/pull/9845)
124+
* [@nexapytech](https://github.com/nexapytech) made their first contribution in [#9867](https://github.com/encode/django-rest-framework/pull/9867)
125+
* [@RispaJoseph](https://github.com/RispaJoseph) made their first contribution in [#9874](https://github.com/encode/django-rest-framework/pull/9874)
126+
* [@LorenzoGuideri](https://github.com/LorenzoGuideri) made their first contribution in [#9875](https://github.com/encode/django-rest-framework/pull/9875)
127+
* [@maldoinc](https://github.com/maldoinc) made their first contribution in [#9893](https://github.com/encode/django-rest-framework/pull/9893)
128+
* [@0Nafi0](https://github.com/0Nafi0) made their first contribution in [#9861](https://github.com/encode/django-rest-framework/pull/9861)
129+
* [@MoeSalah1999](https://github.com/MoeSalah1999) made their first contribution in [#9870](https://github.com/encode/django-rest-framework/pull/9870)
130+
* [@kelsonbrito50](https://github.com/kelsonbrito50) made their first contribution in [#9901](https://github.com/encode/django-rest-framework/pull/9901)
131+
* [@fbozhang](https://github.com/fbozhang) made their first contribution in [#9735](https://github.com/encode/django-rest-framework/pull/9735)
132+
* [@minorytanaka](https://github.com/minorytanaka) made their first contribution in [#9903](https://github.com/encode/django-rest-framework/pull/9903)
133+
* [@kosbemrunal](https://github.com/kosbemrunal) made their first contribution in [#9904](https://github.com/encode/django-rest-framework/pull/9904)
134+
* [@htvictoire](https://github.com/htvictoire) made their first contribution in [#9916](https://github.com/encode/django-rest-framework/pull/9916)
135+
136+
**Full Changelog**: [3.16.1...3.17.0](https://github.com/encode/django-rest-framework/compare/3.16.1...3.17.0)
137+
39138
## 3.16.x series
40139

41140
### 3.16.1

0 commit comments

Comments
 (0)