Skip to content

Commit 277e04a

Browse files
authored
Merge branch 'encode:master' into jsonencoder_ipaddress
2 parents d403188 + f56b85b commit 277e04a

30 files changed

+137
-91
lines changed

.github/workflows/main.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ jobs:
2222
- '3.11'
2323

2424
steps:
25-
- uses: actions/checkout@v3
25+
- uses: actions/checkout@v4
2626

2727
- uses: actions/setup-python@v4
2828
with:

.pre-commit-config.yaml

+7
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,10 @@ repos:
1818
- id: flake8
1919
additional_dependencies:
2020
- flake8-tidy-imports
21+
- repo: https://github.com/adamchainz/blacken-docs
22+
rev: 1.13.0
23+
hooks:
24+
- id: blacken-docs
25+
exclude: ^(?!docs).*$
26+
additional_dependencies:
27+
- black==23.1.0

CONTRIBUTING.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Contributing to REST framework
22

3-
At this point in it's lifespan we consider Django REST framework to be essentially feature-complete. We may accept pull requests that track the continued development of Django versions, but would prefer not to accept new features or code formatting changes.
3+
At this point in its lifespan we consider Django REST framework to be essentially feature-complete. We may accept pull requests that track the continued development of Django versions, but would prefer not to accept new features or code formatting changes.
44

55
Apart from minor documentation changes, the [GitHub discussions page](https://github.com/encode/django-rest-framework/discussions) should generally be your starting point. Please only raise an issue or pull request if you've been recommended to do so after discussion.
66

docs/api-guide/authentication.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -454,7 +454,7 @@ More information can be found in the [Documentation](https://django-rest-durin.r
454454
[basicauth]: https://tools.ietf.org/html/rfc2617
455455
[permission]: permissions.md
456456
[throttling]: throttling.md
457-
[csrf-ajax]: https://docs.djangoproject.com/en/stable/ref/csrf/#ajax
457+
[csrf-ajax]: https://docs.djangoproject.com/en/stable/howto/csrf/#using-csrf-protection-with-ajax
458458
[mod_wsgi_official]: https://modwsgi.readthedocs.io/en/develop/configuration-directives/WSGIPassAuthorization.html
459459
[django-oauth-toolkit-getting-started]: https://django-oauth-toolkit.readthedocs.io/en/latest/rest-framework/getting_started.html
460460
[django-rest-framework-oauth]: https://jpadilla.github.io/django-rest-framework-oauth/

docs/api-guide/caching.md

+8-8
Original file line numberDiff line numberDiff line change
@@ -28,33 +28,33 @@ from rest_framework import viewsets
2828

2929
class UserViewSet(viewsets.ViewSet):
3030
# With cookie: cache requested url for each user for 2 hours
31-
@method_decorator(cache_page(60*60*2))
31+
@method_decorator(cache_page(60 * 60 * 2))
3232
@method_decorator(vary_on_cookie)
3333
def list(self, request, format=None):
3434
content = {
35-
'user_feed': request.user.get_user_feed()
35+
"user_feed": request.user.get_user_feed(),
3636
}
3737
return Response(content)
3838

3939

4040
class ProfileView(APIView):
4141
# With auth: cache requested url for each user for 2 hours
42-
@method_decorator(cache_page(60*60*2))
43-
@method_decorator(vary_on_headers("Authorization",))
42+
@method_decorator(cache_page(60 * 60 * 2))
43+
@method_decorator(vary_on_headers("Authorization"))
4444
def get(self, request, format=None):
4545
content = {
46-
'user_feed': request.user.get_user_feed()
46+
"user_feed": request.user.get_user_feed(),
4747
}
4848
return Response(content)
4949

5050

5151
class PostView(APIView):
5252
# Cache page for the requested url
53-
@method_decorator(cache_page(60*60*2))
53+
@method_decorator(cache_page(60 * 60 * 2))
5454
def get(self, request, format=None):
5555
content = {
56-
'title': 'Post title',
57-
'body': 'Post content'
56+
"title": "Post title",
57+
"body": "Post content",
5858
}
5959
return Response(content)
6060
```

docs/api-guide/schemas.md

+16-10
Original file line numberDiff line numberDiff line change
@@ -94,11 +94,13 @@ urlpatterns = [
9494
# Use the `get_schema_view()` helper to add a `SchemaView` to project URLs.
9595
# * `title` and `description` parameters are passed to `SchemaGenerator`.
9696
# * Provide view name for use with `reverse()`.
97-
path('openapi', get_schema_view(
98-
title="Your Project",
99-
description="API for all things …",
100-
version="1.0.0"
101-
), name='openapi-schema'),
97+
path(
98+
"openapi",
99+
get_schema_view(
100+
title="Your Project", description="API for all things …", version="1.0.0"
101+
),
102+
name="openapi-schema",
103+
),
102104
# ...
103105
]
104106
```
@@ -259,11 +261,13 @@ class CustomSchema(AutoSchema):
259261
"""
260262
AutoSchema subclass using schema_extra_info on the view.
261263
"""
264+
262265
...
263266

267+
264268
class CustomView(APIView):
265269
schema = CustomSchema()
266-
schema_extra_info = ... some extra info ...
270+
schema_extra_info = ... # some extra info
267271
```
268272

269273
Here, the `AutoSchema` subclass goes looking for `schema_extra_info` on the
@@ -278,10 +282,13 @@ class BaseSchema(AutoSchema):
278282
"""
279283
AutoSchema subclass that knows how to use extra_info.
280284
"""
285+
281286
...
282287

288+
283289
class CustomSchema(BaseSchema):
284-
extra_info = ... some extra info ...
290+
extra_info = ... # some extra info
291+
285292

286293
class CustomView(APIView):
287294
schema = CustomSchema()
@@ -302,10 +309,9 @@ class CustomSchema(BaseSchema):
302309
self.extra_info = kwargs.pop("extra_info")
303310
super().__init__(**kwargs)
304311

312+
305313
class CustomView(APIView):
306-
schema = CustomSchema(
307-
extra_info=... some extra info ...
308-
)
314+
schema = CustomSchema(extra_info=...) # some extra info
309315
```
310316

311317
This saves you having to create a custom subclass per-view for a commonly used option.

docs/api-guide/settings.md

+6
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,12 @@ The string that should used for any versioning parameters, such as in the media
163163

164164
Default: `'version'`
165165

166+
#### DEFAULT_VERSIONING_CLASS
167+
168+
The default versioning scheme to use.
169+
170+
Default: `None`
171+
166172
---
167173

168174
## Authentication settings

docs/api-guide/viewsets.md

+13-12
Original file line numberDiff line numberDiff line change
@@ -201,15 +201,16 @@ To view all extra actions, call the `.get_extra_actions()` method.
201201
Extra actions can map additional HTTP methods to separate `ViewSet` methods. For example, the above password set/unset methods could be consolidated into a single route. Note that additional mappings do not accept arguments.
202202

203203
```python
204-
@action(detail=True, methods=['put'], name='Change Password')
205-
def password(self, request, pk=None):
206-
"""Update the user's password."""
207-
...
208-
209-
@password.mapping.delete
210-
def delete_password(self, request, pk=None):
211-
"""Delete the user's password."""
212-
...
204+
@action(detail=True, methods=["put"], name="Change Password")
205+
def password(self, request, pk=None):
206+
"""Update the user's password."""
207+
...
208+
209+
210+
@password.mapping.delete
211+
def delete_password(self, request, pk=None):
212+
"""Delete the user's password."""
213+
...
213214
```
214215

215216
## Reversing action URLs
@@ -220,14 +221,14 @@ Note that the `basename` is provided by the router during `ViewSet` registration
220221

221222
Using the example from the previous section:
222223

223-
```python
224-
>>> view.reverse_action('set-password', args=['1'])
224+
```pycon
225+
>>> view.reverse_action("set-password", args=["1"])
225226
'http://localhost:8000/api/users/1/set_password'
226227
```
227228

228229
Alternatively, you can use the `url_name` attribute set by the `@action` decorator.
229230

230-
```python
231+
```pycon
231232
>>> view.reverse_action(view.set_password.url_name, args=['1'])
232233
'http://localhost:8000/api/users/1/set_password'
233234
```

docs/community/3.10-announcement.md

+7-6
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@ update your REST framework settings to include `DEFAULT_SCHEMA_CLASS` explicitly
4141

4242
```python
4343
REST_FRAMEWORK = {
44-
...
45-
'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema'
44+
...: ...,
45+
"DEFAULT_SCHEMA_CLASS": "rest_framework.schemas.coreapi.AutoSchema",
4646
}
4747
```
4848

@@ -74,10 +74,11 @@ urlpatterns = [
7474
# Use the `get_schema_view()` helper to add a `SchemaView` to project URLs.
7575
# * `title` and `description` parameters are passed to `SchemaGenerator`.
7676
# * Provide view name for use with `reverse()`.
77-
path('openapi', get_schema_view(
78-
title="Your Project",
79-
description="API for all things …"
80-
), name='openapi-schema'),
77+
path(
78+
"openapi",
79+
get_schema_view(title="Your Project", description="API for all things …"),
80+
name="openapi-schema",
81+
),
8182
# ...
8283
]
8384
```

docs/community/3.11-announcement.md

+5-4
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,11 @@ be extracted from the class docstring:
4343

4444
```python
4545
class DocStringExampleListView(APIView):
46-
"""
47-
get: A description of my GET operation.
48-
post: A description of my POST operation.
49-
"""
46+
"""
47+
get: A description of my GET operation.
48+
post: A description of my POST operation.
49+
"""
50+
5051
permission_classes = [permissions.IsAuthenticatedOrReadOnly]
5152

5253
def get(self, request, *args, **kwargs):

docs/community/3.12-announcement.md

+7-5
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ The tags used for a particular view may also be overridden...
4141

4242
```python
4343
class MyOrders(APIView):
44-
schema = AutoSchema(tags=['users', 'orders'])
44+
schema = AutoSchema(tags=["users", "orders"])
4545
...
4646
```
4747

@@ -68,7 +68,7 @@ may be overridden if needed](https://www.django-rest-framework.org/api-guide/sch
6868

6969
```python
7070
class MyOrders(APIView):
71-
schema = AutoSchema(component_name="OrderDetails")
71+
schema = AutoSchema(component_name="OrderDetails")
7272
```
7373

7474
## More Public API
@@ -118,10 +118,11 @@ class SitesSearchView(generics.ListAPIView):
118118
by a search against the site name or location. (Location searches are
119119
matched against the region and country names.)
120120
"""
121+
121122
queryset = Sites.objects.all()
122123
serializer_class = SitesSerializer
123124
filter_backends = [filters.SearchFilter]
124-
search_fields = ['site_name', 'location__region', 'location__country']
125+
search_fields = ["site_name", "location__region", "location__country"]
125126
```
126127

127128
### Searches against annotate fields
@@ -135,10 +136,11 @@ class PublisherSearchView(generics.ListAPIView):
135136
Search for publishers, optionally filtering the search against the average
136137
rating of all their books.
137138
"""
138-
queryset = Publisher.objects.annotate(avg_rating=Avg('book__rating'))
139+
140+
queryset = Publisher.objects.annotate(avg_rating=Avg("book__rating"))
139141
serializer_class = PublisherSerializer
140142
filter_backends = [filters.SearchFilter]
141-
search_fields = ['avg_rating']
143+
search_fields = ["avg_rating"]
142144
```
143145

144146
---

docs/community/3.9-announcement.md

+4-7
Original file line numberDiff line numberDiff line change
@@ -65,15 +65,12 @@ from rest_framework.renderers import JSONOpenAPIRenderer
6565
from django.urls import path
6666

6767
schema_view = get_schema_view(
68-
title='Server Monitoring API',
69-
url='https://www.example.org/api/',
70-
renderer_classes=[JSONOpenAPIRenderer]
68+
title="Server Monitoring API",
69+
url="https://www.example.org/api/",
70+
renderer_classes=[JSONOpenAPIRenderer],
7171
)
7272

73-
urlpatterns = [
74-
path('schema.json', schema_view),
75-
...
76-
]
73+
urlpatterns = [path("schema.json", schema_view), ...]
7774
```
7875

7976
And here's how you can use the `generateschema` management command:

docs/community/release-notes.md

+5-1
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,11 @@ Be sure to upgrade to Python 3 before upgrading to Django REST Framework 3.10.
306306
class NullableCharField(serializers.CharField):
307307
def __init__(self, *args, **kwargs):
308308
super().__init__(*args, **kwargs)
309-
self.validators = [v for v in self.validators if not isinstance(v, ProhibitNullCharactersValidator)]
309+
self.validators = [
310+
v
311+
for v in self.validators
312+
if not isinstance(v, ProhibitNullCharactersValidator)
313+
]
310314
```
311315
* Add `OpenAPIRenderer` and `generate_schema` management command. [#6229][gh6229]
312316
* Add OpenAPIRenderer by default, and add schema docs. [#6233][gh6233]

docs/community/tutorials-and-resources.md

+5
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ There are a wide range of resources available for learning and using Django REST
1919
</a>
2020
</div>
2121

22+
## Courses
23+
24+
* [Developing RESTful APIs with Django REST Framework][developing-restful-apis-with-django-rest-framework]
25+
2226
## Tutorials
2327

2428
* [Beginner's Guide to the Django REST Framework][beginners-guide-to-the-django-rest-framework]
@@ -130,3 +134,4 @@ Want your Django REST Framework talk/tutorial/article to be added to our website
130134
[pycon-us-2017]: https://www.youtube.com/watch?v=Rk6MHZdust4
131135
[django-rest-react-valentinog]: https://www.valentinog.com/blog/tutorial-api-django-rest-react/
132136
[doordash-implementing-rest-apis]: https://doordash.engineering/2013/10/07/implementing-rest-apis-with-embedded-privacy/
137+
[developing-restful-apis-with-django-rest-framework]: https://testdriven.io/courses/django-rest-framework/

docs/index.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ continued development by **[signing up for a paid plan][funding]**.
8686
REST framework requires the following:
8787

8888
* Python (3.6, 3.7, 3.8, 3.9, 3.10, 3.11)
89-
* Django (3.0, 3.1, 3.2, 4.0, 4.1)
89+
* Django (3.0, 3.1, 3.2, 4.0, 4.1, 4.2)
9090

9191
We **highly recommend** and only officially support the latest patch release of
9292
each Python and Django series.

docs/topics/ajax-csrf-cors.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ The best way to deal with CORS in REST framework is to add the required response
3535

3636
[cite]: https://blog.codinghorror.com/preventing-csrf-and-xsrf-attacks/
3737
[csrf]: https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)
38-
[csrf-ajax]: https://docs.djangoproject.com/en/stable/ref/csrf/#ajax
38+
[csrf-ajax]: https://docs.djangoproject.com/en/stable/howto/csrf/#using-csrf-protection-with-ajax
3939
[cors]: https://www.w3.org/TR/cors/
4040
[adamchainz]: https://github.com/adamchainz
4141
[django-cors-headers]: https://github.com/adamchainz/django-cors-headers

docs/topics/documenting-your-api.md

+15-8
Original file line numberDiff line numberDiff line change
@@ -96,10 +96,14 @@ urlpatterns = [
9696
# ...
9797
# Route TemplateView to serve Swagger UI template.
9898
# * Provide `extra_context` with view name of `SchemaView`.
99-
path('swagger-ui/', TemplateView.as_view(
100-
template_name='swagger-ui.html',
101-
extra_context={'schema_url':'openapi-schema'}
102-
), name='swagger-ui'),
99+
path(
100+
"swagger-ui/",
101+
TemplateView.as_view(
102+
template_name="swagger-ui.html",
103+
extra_context={"schema_url": "openapi-schema"},
104+
),
105+
name="swagger-ui",
106+
),
103107
]
104108
```
105109

@@ -145,10 +149,13 @@ urlpatterns = [
145149
# ...
146150
# Route TemplateView to serve the ReDoc template.
147151
# * Provide `extra_context` with view name of `SchemaView`.
148-
path('redoc/', TemplateView.as_view(
149-
template_name='redoc.html',
150-
extra_context={'schema_url':'openapi-schema'}
151-
), name='redoc'),
152+
path(
153+
"redoc/",
154+
TemplateView.as_view(
155+
template_name="redoc.html", extra_context={"schema_url": "openapi-schema"}
156+
),
157+
name="redoc",
158+
),
152159
]
153160
```
154161

requirements/requirements-documentation.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# MkDocs to build our documentation.
2-
mkdocs>=1.1.2,<1.2
2+
mkdocs==1.2.4
33
jinja2>=2.10,<3.1.0 # contextfilter has been renamed
44

55
# pylinkvalidator to check for broken links in documentation.

0 commit comments

Comments
 (0)