Skip to content

Commit febdc70

Browse files
committed
Merge branch 'main' into chore/django-commons
# Conflicts: # docs/community/project-management.md # docs/community/release-notes.md
2 parents 3320e0d + ade172e commit febdc70

Some content is hidden

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

67 files changed

+1472
-1129
lines changed

.github/workflows/main.yml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,19 @@ jobs:
1414
strategy:
1515
matrix:
1616
python-version:
17-
- '3.9'
1817
- '3.10'
1918
- '3.11'
2019
- '3.12'
2120
- '3.13'
21+
- '3.14'
2222

2323
steps:
2424
- uses: actions/checkout@v5
2525

2626
- uses: actions/setup-python@v6
2727
with:
2828
python-version: ${{ matrix.python-version }}
29+
allow-prereleases: true
2930
cache: 'pip'
3031
cache-dependency-path: 'requirements/*.txt'
3132

@@ -39,7 +40,7 @@ jobs:
3940
run: tox run -f py$(echo ${{ matrix.python-version }} | tr -d . | cut -f 1 -d '-')
4041

4142
- name: Run extra tox targets
42-
if: ${{ matrix.python-version == '3.9' }}
43+
if: ${{ matrix.python-version == '3.13' }}
4344
run: |
4445
tox -e base,dist,docs
4546
@@ -56,7 +57,7 @@ jobs:
5657

5758
- uses: actions/setup-python@v6
5859
with:
59-
python-version: '3.9'
60+
python-version: '3.13'
6061

6162
- name: Install dependencies
6263
run: pip install -r requirements/requirements-documentation.txt

.pre-commit-config.yaml

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,49 @@
11
repos:
22
- repo: https://github.com/pre-commit/pre-commit-hooks
3-
rev: v4.5.0
3+
rev: v6.0.0
44
hooks:
55
- id: check-added-large-files
66
- id: check-case-conflict
77
- id: check-json
88
- id: check-merge-conflict
99
- id: check-symlinks
1010
- id: check-toml
11-
- repo: https://github.com/pycqa/isort
12-
rev: 5.13.2
11+
- repo: https://github.com/PyCQA/isort
12+
rev: 7.0.0
1313
hooks:
1414
- id: isort
1515
- repo: https://github.com/PyCQA/flake8
16-
rev: 7.0.0
16+
rev: 7.3.0
1717
hooks:
1818
- id: flake8
1919
additional_dependencies:
2020
- flake8-tidy-imports
2121
- repo: https://github.com/adamchainz/blacken-docs
22-
rev: 1.16.0
22+
rev: 1.20.0
2323
hooks:
2424
- id: blacken-docs
25-
exclude: ^(?!docs).*$
2625
additional_dependencies:
27-
- black==23.1.0
26+
- black==25.9.0
2827
- repo: https://github.com/codespell-project/codespell
2928
# Configuration for codespell is in .codespellrc
30-
rev: v2.2.6
29+
rev: v2.4.1
3130
hooks:
3231
- id: codespell
32+
args: [
33+
"--builtin", "clear,rare,code,names,en-GB_to_en-US",
34+
"--ignore-words", "codespell-ignore-words.txt",
35+
"--skip", "*.css",
36+
]
3337
exclude: locale|kickstarter-announcement.md|coreapi-0.1.1.js
34-
38+
additional_dependencies:
39+
# python doesn't come with a toml parser prior to 3.11
40+
- "tomli; python_version < '3.11'"
3541
- repo: https://github.com/asottile/pyupgrade
36-
rev: v3.19.1
42+
rev: v3.21.0
3743
hooks:
3844
- id: pyupgrade
39-
args: ["--py39-plus", "--keep-percent-format"]
45+
args: ["--py310-plus", "--keep-percent-format"]
46+
- repo: https://github.com/tox-dev/pyproject-fmt
47+
rev: v2.11.0
48+
hooks:
49+
- id: pyproject-fmt

README.md

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ Some reasons you might want to use REST framework:
5454

5555
# Requirements
5656

57-
* Python 3.9+
57+
* Python 3.10+
5858
* Django 4.2, 5.0, 5.1, 5.2
5959

6060
We **highly recommend** and only officially support the latest patch release of
@@ -67,10 +67,11 @@ Install using `pip`...
6767
pip install djangorestframework
6868

6969
Add `'rest_framework'` to your `INSTALLED_APPS` setting.
70+
7071
```python
7172
INSTALLED_APPS = [
72-
...
73-
'rest_framework',
73+
# ...
74+
"rest_framework",
7475
]
7576
```
7677

@@ -99,7 +100,7 @@ from rest_framework import routers, serializers, viewsets
99100
class UserSerializer(serializers.HyperlinkedModelSerializer):
100101
class Meta:
101102
model = User
102-
fields = ['url', 'username', 'email', 'is_staff']
103+
fields = ["url", "username", "email", "is_staff"]
103104

104105

105106
# ViewSets define the view behavior.
@@ -110,13 +111,13 @@ class UserViewSet(viewsets.ModelViewSet):
110111

111112
# Routers provide a way of automatically determining the URL conf.
112113
router = routers.DefaultRouter()
113-
router.register(r'users', UserViewSet)
114+
router.register(r"users", UserViewSet)
114115

115116
# Wire up our API using automatic URL routing.
116117
# Additionally, we include login URLs for the browsable API.
117118
urlpatterns = [
118-
path('', include(router.urls)),
119-
path('api-auth/', include('rest_framework.urls', namespace='rest_framework')),
119+
path("", include(router.urls)),
120+
path("api-auth/", include("rest_framework.urls", namespace="rest_framework")),
120121
]
121122
```
122123

@@ -126,15 +127,15 @@ Add the following to your `settings.py` module:
126127

127128
```python
128129
INSTALLED_APPS = [
129-
... # Make sure to include the default installed apps here.
130-
'rest_framework',
130+
# ... make sure to include the default installed apps here.
131+
"rest_framework",
131132
]
132133

133134
REST_FRAMEWORK = {
134135
# Use Django's standard `django.contrib.auth` permissions,
135136
# or allow read-only access for unauthenticated users.
136-
'DEFAULT_PERMISSION_CLASSES': [
137-
'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly',
137+
"DEFAULT_PERMISSION_CLASSES": [
138+
"rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly",
138139
]
139140
}
140141
```

codespell-ignore-words.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
Tim
2+
assertIn
3+
IAM
4+
endcode
5+
deque
6+
thead

docs/api-guide/authentication.md

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -416,7 +416,7 @@ JSON Web Token is a fairly new standard which can be used for token-based authen
416416

417417
## Hawk HTTP Authentication
418418

419-
The [HawkREST][hawkrest] library builds on the [Mohawk][mohawk] library to let you work with [Hawk][hawk] signed requests and responses in your API. [Hawk][hawk] lets two parties securely communicate with each other using messages signed by a shared key. It is based on [HTTP MAC access authentication][mac] (which was based on parts of [OAuth 1.0][oauth-1.0a]).
419+
The [HawkREST][hawkrest] library builds on the [Mohawk][mohawk] library to let you work with [Hawk][hawk] signed requests and responses in your API. [Hawk][hawk] let's two parties securely communicate with each other using messages signed by a shared key. It is based on [HTTP MAC access authentication][mac] (which was based on parts of [OAuth 1.0][oauth-1.0a]).
420420

421421
## HTTP Signature Authentication
422422

@@ -426,6 +426,11 @@ HTTP Signature (currently a [IETF draft][http-signature-ietf-draft]) provides a
426426

427427
[Djoser][djoser] library provides a set of views to handle basic actions such as registration, login, logout, password reset and account activation. The package works with a custom user model and uses token-based authentication. This is a ready to use REST implementation of the Django authentication system.
428428

429+
## DRF Auth Kit
430+
431+
[DRF Auth Kit][drf-auth-kit] library provides a modern REST authentication solution with JWT cookies, social login, multi-factor authentication, and comprehensive user management. The package offers full type safety, automatic OpenAPI schema generation with DRF Spectacular. It supports multiple authentication types (JWT, DRF Token, or Custom) and includes built-in internationalization for 50+ languages.
432+
433+
429434
## django-rest-auth / dj-rest-auth
430435

431436
This library provides a set of REST API endpoints for registration, authentication (including social media authentication), password reset, retrieve and update user details, etc. By having these API endpoints, your client apps such as AngularJS, iOS, Android, and others can communicate to your Django backend site independently via REST APIs for user management.
@@ -454,7 +459,7 @@ There are currently two forks of this project.
454459

455460
More information can be found in the [Documentation](https://django-rest-durin.readthedocs.io/en/latest/index.html).
456461

457-
## django-pyoidc
462+
## django-pyoidc
458463

459464
[dango-pyoidc][django_pyoidc] adds support for OpenID Connect (OIDC) authentication. This allows you to delegate user management to an Identity Provider, which can be used to implement Single-Sign-On (SSO). It provides support for most uses-cases, such as customizing how token info are mapped to user models, using OIDC audiences for access control, etc.
460465

@@ -497,4 +502,5 @@ More information can be found in the [Documentation](https://django-pyoidc.readt
497502
[django-rest-authemail]: https://github.com/celiao/django-rest-authemail
498503
[django-rest-durin]: https://github.com/eshaan7/django-rest-durin
499504
[login-required-middleware]: https://docs.djangoproject.com/en/stable/ref/middleware/#django.contrib.auth.middleware.LoginRequiredMiddleware
500-
[django-pyoidc] : https://github.com/makinacorpus/django_pyoidc
505+
[django-pyoidc]: https://github.com/makinacorpus/django_pyoidc
506+
[drf-auth-kit]: https://github.com/huynguyengl99/drf-auth-kit

docs/api-guide/fields.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ The `allow_null` option is also available for string fields, although its usage
180180

181181
## EmailField
182182

183-
A text representation, validates the text to be a valid e-mail address.
183+
A text representation, validates the text to be a valid email address.
184184

185185
Corresponds to `django.db.models.fields.EmailField`
186186

@@ -762,7 +762,7 @@ suitable for updating our target object. With `source='*'`, the return from
762762
('y_coordinate', 4),
763763
('x_coordinate', 3)])
764764

765-
For completeness lets do the same thing again but with the nested serializer
765+
For completeness let's do the same thing again but with the nested serializer
766766
approach suggested above:
767767

768768
class NestedCoordinateSerializer(serializers.Serializer):

docs/api-guide/filtering.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ For example:
235235

236236
search_fields = ['=username', '=email']
237237

238-
By default, the search parameter is named `'search'`, but this may be overridden with the `SEARCH_PARAM` setting.
238+
By default, the search parameter is named `'search'`, but this may be overridden with the `SEARCH_PARAM` setting in the `REST_FRAMEWORK` configuration.
239239

240240
To dynamically change search fields based on request content, it's possible to subclass the `SearchFilter` and override the `get_search_fields()` function. For example, the following subclass will only search on `title` if the query parameter `title_only` is in the request:
241241

@@ -257,7 +257,7 @@ The `OrderingFilter` class supports simple query parameter controlled ordering o
257257

258258
![Ordering Filter](../img/ordering-filter.png)
259259

260-
By default, the query parameter is named `'ordering'`, but this may be overridden with the `ORDERING_PARAM` setting.
260+
By default, the query parameter is named `'ordering'`, but this may be overridden with the `ORDERING_PARAM` setting in the `REST_FRAMEWORK` configuration.
261261

262262
For example, to order users by username:
263263

docs/api-guide/generic-views.md

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,39 @@ For example:
102102

103103
---
104104

105+
### Avoiding N+1 Queries
106+
107+
When listing objects (e.g. using `ListAPIView` or `ModelViewSet`), serializers may trigger an N+1 query pattern if related objects are accessed individually for each item.
108+
109+
To prevent this, optimize the queryset in `get_queryset()` or by setting the `queryset` class attribute using [`select_related()`](https://docs.djangoproject.com/en/stable/ref/models/querysets/#select-related) and [`prefetch_related()`](https://docs.djangoproject.com/en/stable/ref/models/querysets/#prefetch-related), depending on the type of relationship.
110+
111+
**For ForeignKey and OneToOneField**:
112+
113+
Use `select_related()` to fetch related objects in the same query:
114+
115+
def get_queryset(self):
116+
return Order.objects.select_related("customer", "billing_address")
117+
118+
**For reverse and many-to-many relationships**:
119+
120+
Use `prefetch_related()` to efficiently load collections of related objects:
121+
122+
def get_queryset(self):
123+
return Book.objects.prefetch_related("categories", "reviews__user")
124+
125+
**Combining both**:
126+
127+
def get_queryset(self):
128+
return (
129+
Order.objects
130+
.select_related("customer")
131+
.prefetch_related("items__product")
132+
)
133+
134+
These optimizations reduce repeated database access and improve list view performance.
135+
136+
---
137+
105138
#### `get_object(self)`
106139

107140
Returns an object instance that should be used for detail views. Defaults to using the `lookup_field` parameter to filter the base queryset.
@@ -374,8 +407,6 @@ Allowing `PUT` as create operations is problematic, as it necessarily exposes in
374407

375408
Both styles "`PUT` as 404" and "`PUT` as create" can be valid in different circumstances, but from version 3.0 onwards we now use 404 behavior as the default, due to it being simpler and more obvious.
376409

377-
If you need to generic PUT-as-create behavior you may want to include something like [this `AllowPUTAsCreateMixin` class](https://gist.github.com/tomchristie/a2ace4577eff2c603b1b) as a mixin to your views.
378-
379410
---
380411

381412
# Third party packages

docs/api-guide/metadata.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ The REST framework package only includes a single metadata class implementation,
6666

6767
## Creating schema endpoints
6868

69-
If you have specific requirements for creating schema endpoints that are accessed with regular `GET` requests, you might consider re-using the metadata API for doing so.
69+
If you have specific requirements for creating schema endpoints that are accessed with regular `GET` requests, you might consider reusing the metadata API for doing so.
7070

7171
For example, the following additional route could be used on a viewset to provide a linkable schema endpoint.
7272

docs/api-guide/pagination.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ To set these attributes you should override the `PageNumberPagination` class, an
108108
* `page_query_param` - A string value indicating the name of the query parameter to use for the pagination control.
109109
* `page_size_query_param` - If set, this is a string value indicating the name of a query parameter that allows the client to set the page size on a per-request basis. Defaults to `None`, indicating that the client may not control the requested page size.
110110
* `max_page_size` - If set, this is a numeric value indicating the maximum allowable requested page size. This attribute is only valid if `page_size_query_param` is also set.
111-
* `last_page_strings` - A list or tuple of string values indicating values that may be used with the `page_query_param` to request the final page in the set. Defaults to `('last',)`
111+
* `last_page_strings` - A list or tuple of string values indicating values that may be used with the `page_query_param` to request the final page in the set. Defaults to `('last',)`. For example, use `?page=last` to go directly to the last page.
112112
* `template` - The name of a template to use when rendering pagination controls in the browsable API. May be overridden to modify the rendering style, or set to `None` to disable HTML pagination controls completely. Defaults to `"rest_framework/pagination/numbers.html"`.
113113

114114
---

0 commit comments

Comments
 (0)