Skip to content

Commit 6f8da97

Browse files
committed
Merge branch 'master' into migrate_setuppy_to_pryoject.toml
2 parents 2770f5e + d3dd45b commit 6f8da97

File tree

83 files changed

+1555
-1793
lines changed

Some content is hidden

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

83 files changed

+1555
-1793
lines changed

.github/ISSUE_TEMPLATE/1-issue.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,13 @@ about: Please only raise an issue if you've been advised to do so after discussi
55

66
## Checklist
77

8+
<!--
9+
Note: REST framework is considered feature-complete. New functionality should be implemented outside the core REST framework. For details, please check the docs: https://www.django-rest-framework.org/community/third-party-packages/#about-third-party-packages
10+
-->
11+
812
- [ ] Raised initially as discussion #...
9-
- [ ] This cannot be dealt with as a third party library. (We prefer new functionality to be [in the form of third party libraries](https://www.django-rest-framework.org/community/third-party-packages/#about-third-party-packages) where possible.)
13+
- [ ] This is not a feature request suitable for implementation outside this project. Please elaborate what it is:
14+
- [ ] compatibility fix for new Django/Python version ...
15+
- [ ] other type of bug fix
16+
- [ ] other type of improvement that does not touch existing code or change existing behavior (e.g. wrapper for new Django field)
1017
- [ ] I have reduced the issue to the simplest possible case.

.github/workflows/main.yml

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,12 @@ jobs:
1414
strategy:
1515
matrix:
1616
python-version:
17-
- '3.6'
18-
- '3.7'
1917
- '3.8'
2018
- '3.9'
2119
- '3.10'
2220
- '3.11'
2321
- '3.12'
22+
- '3.13'
2423

2524
steps:
2625
- uses: actions/checkout@v4
@@ -37,17 +36,8 @@ jobs:
3736
- name: Install dependencies
3837
run: python -m pip install --upgrade codecov tox
3938

40-
- name: Install tox-py
41-
if: ${{ matrix.python-version == '3.6' }}
42-
run: python -m pip install --upgrade tox-py
43-
44-
- name: Run tox targets for ${{ matrix.python-version }}
45-
if: ${{ matrix.python-version != '3.6' }}
46-
run: tox run -f py$(echo ${{ matrix.python-version }} | tr -d .)
47-
4839
- name: Run tox targets for ${{ matrix.python-version }}
49-
if: ${{ matrix.python-version == '3.6' }}
50-
run: tox --py current
40+
run: tox run -f py$(echo ${{ matrix.python-version }} | tr -d . | cut -f 1 -d '-')
5141

5242
- name: Run extra tox targets
5343
if: ${{ matrix.python-version == '3.9' }}

PULL_REQUEST_TEMPLATE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
*Note*: Before submitting this pull request, please review our [contributing guidelines](https://www.django-rest-framework.org/community/contributing/#pull-requests).
1+
*Note*: Before submitting a code change, please review our [contributing guidelines](https://www.django-rest-framework.org/community/contributing/#pull-requests).
22

33
## Description
44

README.md

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,9 @@ The initial aim is to provide a single full-time position on REST framework.
2828
[![][cryptapi-img]][cryptapi-url]
2929
[![][fezto-img]][fezto-url]
3030
[![][svix-img]][svix-url]
31+
[![][zuplo-img]][zuplo-url]
3132

32-
Many thanks to all our [wonderful sponsors][sponsors], and in particular to our premium backers, [Sentry][sentry-url], [Stream][stream-url], [Spacinov][spacinov-url], [Retool][retool-url], [bit.io][bitio-url], [PostHog][posthog-url], [CryptAPI][cryptapi-url], [FEZTO][fezto-url], and [Svix][svix-url].
33+
Many thanks to all our [wonderful sponsors][sponsors], and in particular to our premium backers, [Sentry][sentry-url], [Stream][stream-url], [Spacinov][spacinov-url], [Retool][retool-url], [bit.io][bitio-url], [PostHog][posthog-url], [CryptAPI][cryptapi-url], [FEZTO][fezto-url], [Svix][svix-url], and [Zuplo][zuplo-url].
3334

3435
---
3536

@@ -45,8 +46,6 @@ Some reasons you might want to use REST framework:
4546
* Customizable all the way down - just use [regular function-based views][functionview-section] if you don't need the [more][generic-views] [powerful][viewsets] [features][routers].
4647
* [Extensive documentation][docs], and [great community support][group].
4748

48-
There is a live example API for testing purposes, [available here][sandbox].
49-
5049
**Below**: *Screenshot from the browsable API*
5150

5251
![Screenshot][image]
@@ -55,8 +54,8 @@ There is a live example API for testing purposes, [available here][sandbox].
5554

5655
# Requirements
5756

58-
* Python 3.6+
59-
* Django 5.0, 4.2, 4.1, 4.0, 3.2, 3.1, 3.0
57+
* Python 3.8+
58+
* Django 4.2, 5.0, 5.1
6059

6160
We **highly recommend** and only officially support the latest patch release of
6261
each Python and Django series.
@@ -174,8 +173,6 @@ Full documentation for the project is available at [https://www.django-rest-fram
174173

175174
For questions and support, use the [REST framework discussion group][group], or `#restframework` on libera.chat IRC.
176175

177-
You may also want to [follow the author on Twitter][twitter].
178-
179176
# Security
180177

181178
Please see the [security policy][security-policy].
@@ -186,9 +183,7 @@ Please see the [security policy][security-policy].
186183
[codecov]: https://codecov.io/github/encode/django-rest-framework?branch=master
187184
[pypi-version]: https://img.shields.io/pypi/v/djangorestframework.svg
188185
[pypi]: https://pypi.org/project/djangorestframework/
189-
[twitter]: https://twitter.com/starletdreaming
190186
[group]: https://groups.google.com/forum/?fromgroups#!forum/django-rest-framework
191-
[sandbox]: https://restframework.herokuapp.com/
192187

193188
[funding]: https://fund.django-rest-framework.org/topics/funding/
194189
[sponsors]: https://fund.django-rest-framework.org/topics/funding/#our-sponsors
@@ -202,6 +197,7 @@ Please see the [security policy][security-policy].
202197
[cryptapi-img]: https://raw.githubusercontent.com/encode/django-rest-framework/master/docs/img/premium/cryptapi-readme.png
203198
[fezto-img]: https://raw.githubusercontent.com/encode/django-rest-framework/master/docs/img/premium/fezto-readme.png
204199
[svix-img]: https://raw.githubusercontent.com/encode/django-rest-framework/master/docs/img/premium/svix-premium.png
200+
[zuplo-img]: https://raw.githubusercontent.com/encode/django-rest-framework/master/docs/img/premium/zuplo-readme.png
205201

206202
[sentry-url]: https://getsentry.com/welcome/
207203
[stream-url]: https://getstream.io/?utm_source=DjangoRESTFramework&utm_medium=Webpage_Logo_Ad&utm_content=Developer&utm_campaign=DjangoRESTFramework_Jan2022_HomePage
@@ -212,6 +208,7 @@ Please see the [security policy][security-policy].
212208
[cryptapi-url]: https://cryptapi.io
213209
[fezto-url]: https://www.fezto.xyz/?utm_source=DjangoRESTFramework
214210
[svix-url]: https://www.svix.com/?utm_source=django-REST&utm_medium=sponsorship
211+
[zuplo-url]: https://zuplo.link/django-gh
215212

216213
[oauth1-section]: https://www.django-rest-framework.org/api-guide/authentication/#django-rest-framework-oauth
217214
[oauth2-section]: https://www.django-rest-framework.org/api-guide/authentication/#django-oauth-toolkit

docs/api-guide/authentication.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,12 @@ The kind of response that will be used depends on the authentication scheme. Al
9090

9191
Note that when a request may successfully authenticate, but still be denied permission to perform the request, in which case a `403 Permission Denied` response will always be used, regardless of the authentication scheme.
9292

93+
## Django 5.1+ `LoginRequiredMiddleware`
94+
95+
If you're running Django 5.1+ and use the [`LoginRequiredMiddleware`][login-required-middleware], please note that all views from DRF are opted-out of this middleware. This is because the authentication in DRF is based authentication and permissions classes, which may be determined after the middleware has been applied. Additionally, when the request is not authenticated, the middleware redirects the user to the login page, which is not suitable for API requests, where it's preferable to return a 401 status code.
96+
97+
REST framework offers an equivalent mechanism for DRF views via the global settings, `DEFAULT_AUTHENTICATION_CLASSES` and `DEFAULT_PERMISSION_CLASSES`. They should be changed accordingly if you need to enforce that API requests are logged in.
98+
9399
## Apache mod_wsgi specific configuration
94100

95101
Note that if deploying to [Apache using mod_wsgi][mod_wsgi_official], the authorization header is not passed through to a WSGI application by default, as it is assumed that authentication will be handled by Apache, rather than at an application level.
@@ -484,3 +490,4 @@ More information can be found in the [Documentation](https://django-rest-durin.r
484490
[drfpasswordless]: https://github.com/aaronn/django-rest-framework-passwordless
485491
[django-rest-authemail]: https://github.com/celiao/django-rest-authemail
486492
[django-rest-durin]: https://github.com/eshaan7/django-rest-durin
493+
[login-required-middleware]: https://docs.djangoproject.com/en/stable/ref/middleware/#django.contrib.auth.middleware.LoginRequiredMiddleware

docs/api-guide/caching.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,29 @@ class PostView(APIView):
5959
return Response(content)
6060
```
6161

62+
63+
## Using cache with @api_view decorator
64+
65+
When using @api_view decorator, the Django-provided method-based cache decorators such as [`cache_page`][page],
66+
[`vary_on_cookie`][cookie] and [`vary_on_headers`][headers] can be called directly.
67+
68+
```python
69+
from django.views.decorators.cache import cache_page
70+
from django.views.decorators.vary import vary_on_cookie
71+
72+
from rest_framework.decorators import api_view
73+
from rest_framework.response import Response
74+
75+
76+
@cache_page(60 * 15)
77+
@vary_on_cookie
78+
@api_view(["GET"])
79+
def get_user_list(request):
80+
content = {"user_feed": request.user.get_user_feed()}
81+
return Response(content)
82+
```
83+
84+
6285
**NOTE:** The [`cache_page`][page] decorator only caches the
6386
`GET` and `HEAD` responses with status 200.
6487

docs/api-guide/fields.md

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -68,14 +68,6 @@ When serializing the instance, default will be used if the object attribute or d
6868

6969
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.
7070

71-
Notes regarding default value propagation from model to serializer:
72-
73-
All the default values from model will pass as default to the serializer and the options method.
74-
75-
If the default is callable then it will be propagated to & evaluated every time in the serializer but not in options method.
76-
77-
If the value for given field is not given then default value will be present in the serializer and available in serializer's methods. Specified validation on given field will be evaluated on default value as that field will be present in the serializer.
78-
7971
### `allow_null`
8072

8173
Normally an error will be raised if `None` is passed to a serializer field. Set this keyword argument to `True` if `None` should be considered a valid value.
@@ -299,8 +291,8 @@ Corresponds to `django.db.models.fields.DecimalField`.
299291
* `max_digits` The maximum number of digits allowed in the number. It must be either `None` or an integer greater than or equal to `decimal_places`.
300292
* `decimal_places` The number of decimal places to store with the number.
301293
* `coerce_to_string` Set to `True` if string values should be returned for the representation, or `False` if `Decimal` objects should be returned. Defaults to the same value as the `COERCE_DECIMAL_TO_STRING` settings key, which will be `True` unless overridden. If `Decimal` objects are returned by the serializer, then the final output format will be determined by the renderer. Note that setting `localize` will force the value to `True`.
302-
* `max_value` Validate that the number provided is no greater than this value.
303-
* `min_value` Validate that the number provided is no less than this value.
294+
* `max_value` Validate that the number provided is no greater than this value. Should be an integer or `Decimal` object.
295+
* `min_value` Validate that the number provided is no less than this value. Should be an integer or `Decimal` object.
304296
* `localize` Set to `True` to enable localization of input and output based on the current locale. This will also force `coerce_to_string` to `True`. Defaults to `False`. Note that data formatting is enabled if you have set `USE_L10N=True` in your settings file.
305297
* `rounding` Sets the rounding mode used when quantizing to the configured precision. Valid values are [`decimal` module rounding modes][python-decimal-rounding-modes]. Defaults to `None`.
306298
* `normalize_output` Will normalize the decimal value when serialized. This will strip all trailing zeroes and change the value's precision to the minimum required precision to be able to represent the value without losing data. Defaults to `False`.

docs/api-guide/permissions.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -173,12 +173,11 @@ This permission is suitable if you want to your API to allow read permissions to
173173

174174
This permission class ties into Django's standard `django.contrib.auth` [model permissions][contribauth]. This permission must only be applied to views that have a `.queryset` property or `get_queryset()` method. Authorization will only be granted if the user *is authenticated* and has the *relevant model permissions* assigned. The appropriate model is determined by checking `get_queryset().model` or `queryset.model`.
175175

176-
* `GET` requests require the user to have the `view` or `change` permission on the model
177176
* `POST` requests require the user to have the `add` permission on the model.
178177
* `PUT` and `PATCH` requests require the user to have the `change` permission on the model.
179178
* `DELETE` requests require the user to have the `delete` permission on the model.
180179

181-
The default behaviour can also be overridden to support custom model permissions.
180+
The default behavior can also be overridden to support custom model permissions. For example, you might want to include a `view` model permission for `GET` requests.
182181

183182
To use custom model permissions, override `DjangoModelPermissions` and set the `.perms_map` property. Refer to the source code for details.
184183

docs/api-guide/renderers.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ By default this will include the following keys: `view`, `request`, `response`,
283283

284284
The following is an example plaintext renderer that will return a response with the `data` parameter as the content of the response.
285285

286-
from django.utils.encoding import smart_text
286+
from django.utils.encoding import smart_str
287287
from rest_framework import renderers
288288

289289

@@ -292,7 +292,7 @@ The following is an example plaintext renderer that will return a response with
292292
format = 'txt'
293293

294294
def render(self, data, accepted_media_type=None, renderer_context=None):
295-
return smart_text(data, encoding=self.charset)
295+
return smart_str(data, encoding=self.charset)
296296

297297
## Setting the character set
298298

docs/api-guide/routers.md

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,24 @@ The above example would now generate the following URL pattern:
142142
* URL path: `^users/{pk}/change-password/$`
143143
* URL name: `'user-change_password'`
144144

145+
### Using Django `path()` with routers
146+
147+
By default, the URLs created by routers use regular expressions. This behavior can be modified by setting the `use_regex_path` argument to `False` when instantiating the router, in this case [path converters][path-converters-topic-reference] are used. For example:
148+
149+
router = SimpleRouter(use_regex_path=False)
150+
151+
The router will match lookup values containing any characters except slashes and period characters. For a more restrictive (or lenient) lookup pattern, set the `lookup_value_regex` attribute on the viewset or `lookup_value_converter` if using path converters. For example, you can limit the lookup to valid UUIDs:
152+
153+
class MyModelViewSet(mixins.RetrieveModelMixin, viewsets.GenericViewSet):
154+
lookup_field = 'my_model_id'
155+
lookup_value_regex = '[0-9a-f]{32}'
156+
157+
class MyPathModelViewSet(mixins.RetrieveModelMixin, viewsets.GenericViewSet):
158+
lookup_field = 'my_model_uuid'
159+
lookup_value_converter = 'uuid'
160+
161+
Note that path converters will be used on all URLs registered in the router, including viewset actions.
162+
145163
# API Guide
146164

147165
## SimpleRouter
@@ -160,30 +178,13 @@ This router includes routes for the standard set of `list`, `create`, `retrieve`
160178
<tr><td>{prefix}/{lookup}/{url_path}/</td><td>GET, or as specified by `methods` argument</td><td>`@action(detail=True)` decorated method</td><td>{basename}-{url_name}</td></tr>
161179
</table>
162180

163-
By default the URLs created by `SimpleRouter` are appended with a trailing slash.
181+
By default, the URLs created by `SimpleRouter` are appended with a trailing slash.
164182
This behavior can be modified by setting the `trailing_slash` argument to `False` when instantiating the router. For example:
165183

166184
router = SimpleRouter(trailing_slash=False)
167185

168186
Trailing slashes are conventional in Django, but are not used by default in some other frameworks such as Rails. Which style you choose to use is largely a matter of preference, although some javascript frameworks may expect a particular routing style.
169187

170-
By default the URLs created by `SimpleRouter` use regular expressions. This behavior can be modified by setting the `use_regex_path` argument to `False` when instantiating the router, in this case [path converters][path-converters-topic-reference] are used. For example:
171-
172-
router = SimpleRouter(use_regex_path=False)
173-
174-
**Note**: `use_regex_path=False` only works with Django 2.x or above, since this feature was introduced in 2.0.0. See [release note][simplified-routing-release-note]
175-
176-
177-
The router will match lookup values containing any characters except slashes and period characters. For a more restrictive (or lenient) lookup pattern, set the `lookup_value_regex` attribute on the viewset or `lookup_value_converter` if using path converters. For example, you can limit the lookup to valid UUIDs:
178-
179-
class MyModelViewSet(mixins.RetrieveModelMixin, viewsets.GenericViewSet):
180-
lookup_field = 'my_model_id'
181-
lookup_value_regex = '[0-9a-f]{32}'
182-
183-
class MyPathModelViewSet(mixins.RetrieveModelMixin, viewsets.GenericViewSet):
184-
lookup_field = 'my_model_uuid'
185-
lookup_value_converter = 'uuid'
186-
187188
## DefaultRouter
188189

189190
This router is similar to `SimpleRouter` as above, but additionally includes a default API root view, that returns a response containing hyperlinks to all the list views. It also generates routes for optional `.json` style format suffixes.
@@ -351,5 +352,4 @@ The [`DRF-extensions` package][drf-extensions] provides [routers][drf-extensions
351352
[drf-extensions-customizable-endpoint-names]: https://chibisov.github.io/drf-extensions/docs/#controller-endpoint-name
352353
[url-namespace-docs]: https://docs.djangoproject.com/en/4.0/topics/http/urls/#url-namespaces
353354
[include-api-reference]: https://docs.djangoproject.com/en/4.0/ref/urls/#include
354-
[simplified-routing-release-note]: https://docs.djangoproject.com/en/2.0/releases/2.0/#simplified-url-routing-syntax
355355
[path-converters-topic-reference]: https://docs.djangoproject.com/en/2.0/topics/http/urls/#path-converters

0 commit comments

Comments
 (0)