Skip to content

Commit 0880ed9

Browse files
authored
Merge branch 'encode:master' into jsonencoder_ipaddress
2 parents a4f4dd0 + 28d0261 commit 0880ed9

Some content is hidden

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

48 files changed

+413
-148
lines changed

.github/workflows/main.yml

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ jobs:
1919
- '3.10'
2020
- '3.11'
2121
- '3.12'
22+
- '3.13'
2223

2324
steps:
2425
- uses: actions/checkout@v4
@@ -33,19 +34,20 @@ jobs:
3334
run: python -m pip install --upgrade pip setuptools virtualenv wheel
3435

3536
- name: Install dependencies
36-
run: python -m pip install --upgrade codecov tox
37+
run: python -m pip install --upgrade tox
3738

3839
- name: Run tox targets for ${{ matrix.python-version }}
39-
run: tox run -f py$(echo ${{ matrix.python-version }} | tr -d .)
40+
run: tox run -f py$(echo ${{ matrix.python-version }} | tr -d . | cut -f 1 -d '-')
4041

4142
- name: Run extra tox targets
4243
if: ${{ matrix.python-version == '3.9' }}
4344
run: |
4445
tox -e base,dist,docs
4546
4647
- name: Upload coverage
47-
run: |
48-
codecov -e TOXENV,DJANGO
48+
uses: codecov/codecov-action@v5
49+
with:
50+
env_vars: TOXENV,DJANGO
4951

5052
test-docs:
5153
name: Test documentation links

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ Some reasons you might want to use REST framework:
5555
# Requirements
5656

5757
* Python 3.8+
58-
* Django 5.0, 4.2
58+
* Django 4.2, 5.0, 5.1
5959

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

SECURITY.md

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22

33
## Reporting a Vulnerability
44

5-
Security issues are handled under the supervision of the [Django security team](https://www.djangoproject.com/foundation/teams/#security-team).
5+
**Please report security issues by emailing security@encode.io**.
66

7-
**Please report security issues by emailing [email protected]**.
8-
9-
The project maintainers will then work with you to resolve any issues where required, prior to any public disclosure.
7+
The project maintainers will then work with you to resolve any issues where required, prior to any public disclosure.

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/fields.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -291,8 +291,8 @@ Corresponds to `django.db.models.fields.DecimalField`.
291291
* `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`.
292292
* `decimal_places` The number of decimal places to store with the number.
293293
* `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`.
294-
* `max_value` Validate that the number provided is no greater than this value.
295-
* `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.
296296
* `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.
297297
* `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`.
298298
* `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/renderers.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -525,7 +525,7 @@ Comma-separated values are a plain-text tabular data format, that can be easily
525525

526526
## LaTeX
527527

528-
[Rest Framework Latex] provides a renderer that outputs PDFs using Laulatex. It is maintained by [Pebble (S/F Software)][mypebble].
528+
[Rest Framework Latex] provides a renderer that outputs PDFs using Lualatex. It is maintained by [Pebble (S/F Software)][mypebble].
529529

530530

531531
[cite]: https://docs.djangoproject.com/en/stable/ref/template-response/#the-rendering-process

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

docs/api-guide/serializers.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ Serializer classes can also include reusable validators that are applied to the
233233

234234
class EventSerializer(serializers.Serializer):
235235
name = serializers.CharField()
236-
room_number = serializers.IntegerField(choices=[101, 102, 103, 201])
236+
room_number = serializers.ChoiceField(choices=[101, 102, 103, 201])
237237
date = serializers.DateField()
238238

239239
class Meta:

docs/api-guide/settings.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -460,4 +460,4 @@ Default: `None`
460460
[cite]: https://www.python.org/dev/peps/pep-0020/
461461
[rfc4627]: https://www.ietf.org/rfc/rfc4627.txt
462462
[heroku-minified-json]: https://github.com/interagent/http-api-design#keep-json-minified-in-all-responses
463-
[strftime]: https://docs.python.org/3/library/time.html#time.strftime
463+
[strftime]: https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes

docs/api-guide/testing.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,12 @@ The `APIRequestFactory` class supports an almost identical API to Django's stand
2525
factory = APIRequestFactory()
2626
request = factory.post('/notes/', {'title': 'new idea'})
2727

28+
# Using the standard RequestFactory API to encode JSON data
29+
request = factory.post('/notes/', {'title': 'new idea'}, content_type='application/json')
30+
2831
#### Using the `format` argument
2932

30-
Methods which create a request body, such as `post`, `put` and `patch`, include a `format` argument, which make it easy to generate requests using a content type other than multipart form data. For example:
33+
Methods which create a request body, such as `post`, `put` and `patch`, include a `format` argument, which make it easy to generate requests using a wide set of request formats. When using this argument, the factory will select an appropriate renderer and its configured `content_type`. For example:
3134

3235
# Create a JSON POST request
3336
factory = APIRequestFactory()
@@ -41,7 +44,7 @@ To support a wider set of request formats, or change the default format, [see th
4144

4245
If you need to explicitly encode the request body, you can do so by setting the `content_type` flag. For example:
4346

44-
request = factory.post('/notes/', json.dumps({'title': 'new idea'}), content_type='application/json')
47+
request = factory.post('/notes/', yaml.dump({'title': 'new idea'}), content_type='application/yaml')
4548

4649
#### PUT and PATCH with form data
4750

0 commit comments

Comments
 (0)