Merge branch 'master' into third_party_package_for_exception_handling
16
README.md
|
@ -21,14 +21,14 @@ The initial aim is to provide a single full-time position on REST framework.
|
||||||
|
|
||||||
[![][sentry-img]][sentry-url]
|
[![][sentry-img]][sentry-url]
|
||||||
[![][stream-img]][stream-url]
|
[![][stream-img]][stream-url]
|
||||||
[![][rollbar-img]][rollbar-url]
|
[![][spacinov-img]][spacinov-url]
|
||||||
[![][esg-img]][esg-url]
|
|
||||||
[![][retool-img]][retool-url]
|
[![][retool-img]][retool-url]
|
||||||
[![][bitio-img]][bitio-url]
|
[![][bitio-img]][bitio-url]
|
||||||
[![][posthog-img]][posthog-url]
|
[![][posthog-img]][posthog-url]
|
||||||
[![][cryptapi-img]][cryptapi-url]
|
[![][cryptapi-img]][cryptapi-url]
|
||||||
|
[![][fezto-img]][fezto-url]
|
||||||
|
|
||||||
Many thanks to all our [wonderful sponsors][sponsors], and in particular to our premium backers, [Sentry][sentry-url], [Stream][stream-url], [Rollbar][rollbar-url], [ESG][esg-url], [Retool][retool-url], [bit.io][bitio-url], [PostHog][posthog-url], and [CryptAPI][cryptapi-url].
|
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], and [FEZTO][fezto-url].
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@ There is a live example API for testing purposes, [available here][sandbox].
|
||||||
# Requirements
|
# Requirements
|
||||||
|
|
||||||
* Python (3.6, 3.7, 3.8, 3.9, 3.10)
|
* Python (3.6, 3.7, 3.8, 3.9, 3.10)
|
||||||
* Django (2.2, 3.0, 3.1, 3.2, 4.0)
|
* Django (2.2, 3.0, 3.1, 3.2, 4.0, 4.1)
|
||||||
|
|
||||||
We **highly recommend** and only officially support the latest patch release of
|
We **highly recommend** and only officially support the latest patch release of
|
||||||
each Python and Django series.
|
each Python and Django series.
|
||||||
|
@ -194,21 +194,21 @@ Please see the [security policy][security-policy].
|
||||||
|
|
||||||
[sentry-img]: https://raw.githubusercontent.com/encode/django-rest-framework/master/docs/img/premium/sentry-readme.png
|
[sentry-img]: https://raw.githubusercontent.com/encode/django-rest-framework/master/docs/img/premium/sentry-readme.png
|
||||||
[stream-img]: https://raw.githubusercontent.com/encode/django-rest-framework/master/docs/img/premium/stream-readme.png
|
[stream-img]: https://raw.githubusercontent.com/encode/django-rest-framework/master/docs/img/premium/stream-readme.png
|
||||||
[rollbar-img]: https://raw.githubusercontent.com/encode/django-rest-framework/master/docs/img/premium/rollbar-readme.png
|
[spacinov-img]: https://raw.githubusercontent.com/encode/django-rest-framework/master/docs/img/premium/spacinov-readme.png
|
||||||
[esg-img]: https://raw.githubusercontent.com/encode/django-rest-framework/master/docs/img/premium/esg-readme.png
|
|
||||||
[retool-img]: https://raw.githubusercontent.com/encode/django-rest-framework/master/docs/img/premium/retool-readme.png
|
[retool-img]: https://raw.githubusercontent.com/encode/django-rest-framework/master/docs/img/premium/retool-readme.png
|
||||||
[bitio-img]: https://raw.githubusercontent.com/encode/django-rest-framework/master/docs/img/premium/bitio-readme.png
|
[bitio-img]: https://raw.githubusercontent.com/encode/django-rest-framework/master/docs/img/premium/bitio-readme.png
|
||||||
[posthog-img]: https://raw.githubusercontent.com/encode/django-rest-framework/master/docs/img/premium/posthog-readme.png
|
[posthog-img]: https://raw.githubusercontent.com/encode/django-rest-framework/master/docs/img/premium/posthog-readme.png
|
||||||
[cryptapi-img]: https://raw.githubusercontent.com/encode/django-rest-framework/master/docs/img/premium/cryptapi-readme.png
|
[cryptapi-img]: https://raw.githubusercontent.com/encode/django-rest-framework/master/docs/img/premium/cryptapi-readme.png
|
||||||
|
[fezto-img]: https://raw.githubusercontent.com/encode/django-rest-framework/master/docs/img/premium/fezto-readme.png
|
||||||
|
|
||||||
[sentry-url]: https://getsentry.com/welcome/
|
[sentry-url]: https://getsentry.com/welcome/
|
||||||
[stream-url]: https://getstream.io/?utm_source=DjangoRESTFramework&utm_medium=Webpage_Logo_Ad&utm_content=Developer&utm_campaign=DjangoRESTFramework_Jan2022_HomePage
|
[stream-url]: https://getstream.io/?utm_source=DjangoRESTFramework&utm_medium=Webpage_Logo_Ad&utm_content=Developer&utm_campaign=DjangoRESTFramework_Jan2022_HomePage
|
||||||
[rollbar-url]: https://rollbar.com/?utm_source=django&utm_medium=sponsorship&utm_campaign=freetrial
|
[spacinov-url]: https://www.spacinov.com/
|
||||||
[esg-url]: https://software.esg-usa.com/
|
|
||||||
[retool-url]: https://retool.com/?utm_source=djangorest&utm_medium=sponsorship
|
[retool-url]: https://retool.com/?utm_source=djangorest&utm_medium=sponsorship
|
||||||
[bitio-url]: https://bit.io/jobs?utm_source=DRF&utm_medium=sponsor&utm_campaign=DRF_sponsorship
|
[bitio-url]: https://bit.io/jobs?utm_source=DRF&utm_medium=sponsor&utm_campaign=DRF_sponsorship
|
||||||
[posthog-url]: https://posthog.com?utm_source=drf&utm_medium=sponsorship&utm_campaign=open-source-sponsorship
|
[posthog-url]: https://posthog.com?utm_source=drf&utm_medium=sponsorship&utm_campaign=open-source-sponsorship
|
||||||
[cryptapi-url]: https://cryptapi.io
|
[cryptapi-url]: https://cryptapi.io
|
||||||
|
[fezto-url]: https://www.fezto.xyz/?utm_source=DjangoRESTFramework
|
||||||
|
|
||||||
[oauth1-section]: https://www.django-rest-framework.org/api-guide/authentication/#django-rest-framework-oauth
|
[oauth1-section]: https://www.django-rest-framework.org/api-guide/authentication/#django-rest-framework-oauth
|
||||||
[oauth2-section]: https://www.django-rest-framework.org/api-guide/authentication/#django-oauth-toolkit
|
[oauth2-section]: https://www.django-rest-framework.org/api-guide/authentication/#django-oauth-toolkit
|
||||||
|
|
|
@ -120,6 +120,14 @@ Unauthenticated responses that are denied permission will result in an `HTTP 401
|
||||||
|
|
||||||
## TokenAuthentication
|
## TokenAuthentication
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Note:** The token authentication provided by Django REST framework is a fairly simple implementation.
|
||||||
|
|
||||||
|
For an implementation which allows more than one token per user, has some tighter security implementation details, and supports token expiry, please see the [Django REST Knox][django-rest-knox] third party package.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
This authentication scheme uses a simple token-based HTTP Authentication scheme. Token authentication is appropriate for client-server setups, such as native desktop and mobile clients.
|
This authentication scheme uses a simple token-based HTTP Authentication scheme. Token authentication is appropriate for client-server setups, such as native desktop and mobile clients.
|
||||||
|
|
||||||
To use the `TokenAuthentication` scheme you'll need to [configure the authentication classes](#setting-the-authentication-scheme) to include `TokenAuthentication`, and additionally include `rest_framework.authtoken` in your `INSTALLED_APPS` setting:
|
To use the `TokenAuthentication` scheme you'll need to [configure the authentication classes](#setting-the-authentication-scheme) to include `TokenAuthentication`, and additionally include `rest_framework.authtoken` in your `INSTALLED_APPS` setting:
|
||||||
|
@ -129,11 +137,9 @@ To use the `TokenAuthentication` scheme you'll need to [configure the authentica
|
||||||
'rest_framework.authtoken'
|
'rest_framework.authtoken'
|
||||||
]
|
]
|
||||||
|
|
||||||
---
|
Make sure to run `manage.py migrate` after changing your settings.
|
||||||
|
|
||||||
**Note:** Make sure to run `manage.py migrate` after changing your settings. The `rest_framework.authtoken` app provides Django database migrations.
|
The `rest_framework.authtoken` app provides Django database migrations.
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
You'll also need to create tokens for your users.
|
You'll also need to create tokens for your users.
|
||||||
|
|
||||||
|
@ -146,7 +152,7 @@ For clients to authenticate, the token key should be included in the `Authorizat
|
||||||
|
|
||||||
Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b
|
Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b
|
||||||
|
|
||||||
**Note:** If you want to use a different keyword in the header, such as `Bearer`, simply subclass `TokenAuthentication` and set the `keyword` class variable.
|
*If you want to use a different keyword in the header, such as `Bearer`, simply subclass `TokenAuthentication` and set the `keyword` class variable.*
|
||||||
|
|
||||||
If successfully authenticated, `TokenAuthentication` provides the following credentials.
|
If successfully authenticated, `TokenAuthentication` provides the following credentials.
|
||||||
|
|
||||||
|
@ -355,6 +361,10 @@ The following example will authenticate any incoming request as the user given b
|
||||||
|
|
||||||
The following third-party packages are also available.
|
The following third-party packages are also available.
|
||||||
|
|
||||||
|
## django-rest-knox
|
||||||
|
|
||||||
|
[Django-rest-knox][django-rest-knox] library provides models and views to handle token-based authentication in a more secure and extensible way than the built-in TokenAuthentication scheme - with Single Page Applications and Mobile clients in mind. It provides per-client tokens, and views to generate them when provided some other authentication (usually basic authentication), to delete the token (providing a server enforced logout) and to delete all tokens (logs out all clients that a user is logged into).
|
||||||
|
|
||||||
## Django OAuth Toolkit
|
## Django OAuth Toolkit
|
||||||
|
|
||||||
The [Django OAuth Toolkit][django-oauth-toolkit] package provides OAuth 2.0 support and works with Python 3.4+. The package is maintained by [jazzband][jazzband] and uses the excellent [OAuthLib][oauthlib]. The package is well documented, and well supported and is currently our **recommended package for OAuth 2.0 support**.
|
The [Django OAuth Toolkit][django-oauth-toolkit] package provides OAuth 2.0 support and works with Python 3.4+. The package is maintained by [jazzband][jazzband] and uses the excellent [OAuthLib][oauthlib]. The package is well documented, and well supported and is currently our **recommended package for OAuth 2.0 support**.
|
||||||
|
@ -422,11 +432,7 @@ There are currently two forks of this project.
|
||||||
|
|
||||||
## drf-social-oauth2
|
## drf-social-oauth2
|
||||||
|
|
||||||
[Drf-social-oauth2][drf-social-oauth2] is a framework that helps you authenticate with major social oauth2 vendors, such as Facebook, Google, Twitter, Orcid, etc. It generates tokens in a JWTed way with an easy setup.
|
[Drf-social-oauth2][drf-social-oauth2] is a framework that helps you authenticate with major social oauth2 vendors, such as Facebook, Google, Twitter, Orcid, etc. It generates tokens in a JWTed way with an easy setup.
|
||||||
|
|
||||||
## django-rest-knox
|
|
||||||
|
|
||||||
[Django-rest-knox][django-rest-knox] library provides models and views to handle token-based authentication in a more secure and extensible way than the built-in TokenAuthentication scheme - with Single Page Applications and Mobile clients in mind. It provides per-client tokens, and views to generate them when provided some other authentication (usually basic authentication), to delete the token (providing a server enforced logout) and to delete all tokens (logs out all clients that a user is logged into).
|
|
||||||
|
|
||||||
## drfpasswordless
|
## drfpasswordless
|
||||||
|
|
||||||
|
|
|
@ -148,6 +148,7 @@ To submit new content, [open an issue][drf-create-issue] or [create a pull reque
|
||||||
* [django-elasticsearch-dsl-drf][django-elasticsearch-dsl-drf] - Integrate Elasticsearch DSL with Django REST framework. Package provides views, serializers, filter backends, pagination and other handy add-ons.
|
* [django-elasticsearch-dsl-drf][django-elasticsearch-dsl-drf] - Integrate Elasticsearch DSL with Django REST framework. Package provides views, serializers, filter backends, pagination and other handy add-ons.
|
||||||
* [django-api-client][django-api-client] - DRF client that groups the Endpoint response, for use in CBVs and FBV as if you were working with Django's Native Models..
|
* [django-api-client][django-api-client] - DRF client that groups the Endpoint response, for use in CBVs and FBV as if you were working with Django's Native Models..
|
||||||
* [fast-drf] - A model based library for making API development faster and easier.
|
* [fast-drf] - A model based library for making API development faster and easier.
|
||||||
|
* [django-requestlogs] - Providing middleware and other helpers for audit logging for REST framework.
|
||||||
* [drf-standardized-errors][drf-standardized-errors] - DRF exception handler to standardize error responses for all API endpoints.
|
* [drf-standardized-errors][drf-standardized-errors] - DRF exception handler to standardize error responses for all API endpoints.
|
||||||
|
|
||||||
[cite]: http://www.software-ecosystems.com/Software_Ecosystems/Ecosystems.html
|
[cite]: http://www.software-ecosystems.com/Software_Ecosystems/Ecosystems.html
|
||||||
|
@ -238,4 +239,5 @@ To submit new content, [open an issue][drf-create-issue] or [create a pull reque
|
||||||
[graphwrap]: https://github.com/PaulGilmartin/graph_wrap
|
[graphwrap]: https://github.com/PaulGilmartin/graph_wrap
|
||||||
[rest-framework-actions]: https://github.com/AlexisMunera98/rest-framework-actions
|
[rest-framework-actions]: https://github.com/AlexisMunera98/rest-framework-actions
|
||||||
[fast-drf]: https://github.com/iashraful/fast-drf
|
[fast-drf]: https://github.com/iashraful/fast-drf
|
||||||
|
[django-requestlogs]: https://github.com/Raekkeri/django-requestlogs
|
||||||
[drf-standardized-errors]: https://github.com/ghazi-git/drf-standardized-errors
|
[drf-standardized-errors]: https://github.com/ghazi-git/drf-standardized-errors
|
||||||
|
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
BIN
docs/img/premium/fezto-readme.png
Normal file
After Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 4.8 KiB |
Before Width: | Height: | Size: 8.8 KiB After Width: | Height: | Size: 8.7 KiB |
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB |
BIN
docs/img/premium/spacinov-readme.png
Normal file
After Width: | Height: | Size: 56 KiB |
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
|
@ -68,16 +68,16 @@ continued development by **[signing up for a paid plan][funding]**.
|
||||||
<ul class="premium-promo promo">
|
<ul class="premium-promo promo">
|
||||||
<li><a href="https://getsentry.com/welcome/" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/sentry130.png)">Sentry</a></li>
|
<li><a href="https://getsentry.com/welcome/" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/sentry130.png)">Sentry</a></li>
|
||||||
<li><a href="https://getstream.io/?utm_source=DjangoRESTFramework&utm_medium=Webpage_Logo_Ad&utm_content=Developer&utm_campaign=DjangoRESTFramework_Jan2022_HomePage" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/stream-130.png)">Stream</a></li>
|
<li><a href="https://getstream.io/?utm_source=DjangoRESTFramework&utm_medium=Webpage_Logo_Ad&utm_content=Developer&utm_campaign=DjangoRESTFramework_Jan2022_HomePage" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/stream-130.png)">Stream</a></li>
|
||||||
<li><a href="https://software.esg-usa.com" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/esg-new-logo.png)">ESG</a></li>
|
<li><a href="https://www.spacinov.com/" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/spacinov.png)">Spacinov</a></li>
|
||||||
<li><a href="https://rollbar.com" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/rollbar2.png)">Rollbar</a></li>
|
|
||||||
<li><a href="https://retool.com/?utm_source=djangorest&utm_medium=sponsorship" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/retool-sidebar.png)">Retool</a></li>
|
<li><a href="https://retool.com/?utm_source=djangorest&utm_medium=sponsorship" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/retool-sidebar.png)">Retool</a></li>
|
||||||
<li><a href="https://bit.io/jobs?utm_source=DRF&utm_medium=sponsor&utm_campaign=DRF_sponsorship" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/bitio_logo_gold_background.png)">bit.io</a></li>
|
<li><a href="https://bit.io/jobs?utm_source=DRF&utm_medium=sponsor&utm_campaign=DRF_sponsorship" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/bitio_logo_gold_background.png)">bit.io</a></li>
|
||||||
<li><a href="https://posthog.com?utm_source=DRF&utm_medium=sponsor&utm_campaign=DRF_sponsorship" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/135996800-d49fe024-32d9-441a-98d9-4c7596287a67.png)">PostHog</a></li>
|
<li><a href="https://posthog.com?utm_source=DRF&utm_medium=sponsor&utm_campaign=DRF_sponsorship" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/135996800-d49fe024-32d9-441a-98d9-4c7596287a67.png)">PostHog</a></li>
|
||||||
<li><a href="https://cryptapi.io" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/cryptapi.png)">CryptAPI</a></li>
|
<li><a href="https://cryptapi.io" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/cryptapi.png)">CryptAPI</a></li>
|
||||||
|
<li><a href="https://www.fezto.xyz/?utm_source=DjangoRESTFramework" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/fezto.png)">FEZTO</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
<div style="clear: both; padding-bottom: 20px;"></div>
|
<div style="clear: both; padding-bottom: 20px;"></div>
|
||||||
|
|
||||||
*Many thanks to all our [wonderful sponsors][sponsors], and in particular to our premium backers, [Sentry](https://getsentry.com/welcome/), [Stream](https://getstream.io/?utm_source=DjangoRESTFramework&utm_medium=Webpage_Logo_Ad&utm_content=Developer&utm_campaign=DjangoRESTFramework_Jan2022_HomePage), [ESG](https://software.esg-usa.com/), [Rollbar](https://rollbar.com/?utm_source=django&utm_medium=sponsorship&utm_campaign=freetrial), [Cadre](https://cadre.com), [Kloudless](https://hubs.ly/H0f30Lf0), [Lights On Software](https://lightsonsoftware.com), [Retool](https://retool.com/?utm_source=djangorest&utm_medium=sponsorship), [bit.io](https://bit.io/jobs?utm_source=DRF&utm_medium=sponsor&utm_campaign=DRF_sponsorship), [PostHog](https://posthog.com?utm_source=DRF&utm_medium=sponsor&utm_campaign=DRF_sponsorship), and [CryptAPI](https://cryptapi.io).*
|
*Many thanks to all our [wonderful sponsors][sponsors], and in particular to our premium backers, [Sentry](https://getsentry.com/welcome/), [Stream](https://getstream.io/?utm_source=DjangoRESTFramework&utm_medium=Webpage_Logo_Ad&utm_content=Developer&utm_campaign=DjangoRESTFramework_Jan2022_HomePage), [Spacinov](https://www.spacinov.com/), [Retool](https://retool.com/?utm_source=djangorest&utm_medium=sponsorship), [bit.io](https://bit.io/jobs?utm_source=DRF&utm_medium=sponsor&utm_campaign=DRF_sponsorship), [PostHog](https://posthog.com?utm_source=DRF&utm_medium=sponsor&utm_campaign=DRF_sponsorship), [CryptAPI](https://cryptapi.io), and [FEZTO](https://www.fezto.xyz/?utm_source=DjangoRESTFramework).*
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
@ -86,7 +86,7 @@ continued development by **[signing up for a paid plan][funding]**.
|
||||||
REST framework requires the following:
|
REST framework requires the following:
|
||||||
|
|
||||||
* Python (3.6, 3.7, 3.8, 3.9, 3.10)
|
* Python (3.6, 3.7, 3.8, 3.9, 3.10)
|
||||||
* Django (2.2, 3.0, 3.1, 3.2, 4.0)
|
* Django (2.2, 3.0, 3.1, 3.2, 4.0, 4.1)
|
||||||
|
|
||||||
We **highly recommend** and only officially support the latest patch release of
|
We **highly recommend** and only officially support the latest patch release of
|
||||||
each Python and Django series.
|
each Python and Django series.
|
||||||
|
|
|
@ -1,2 +1,3 @@
|
||||||
# MkDocs to build our documentation.
|
# MkDocs to build our documentation.
|
||||||
mkdocs>=1.1.2,<1.2
|
mkdocs>=1.1.2,<1.2
|
||||||
|
jinja2>=2.10,<3.1.0 # contextfilter has been renamed
|
||||||
|
|
|
@ -27,7 +27,6 @@ from django.utils.duration import duration_string
|
||||||
from django.utils.encoding import is_protected_type, smart_str
|
from django.utils.encoding import is_protected_type, smart_str
|
||||||
from django.utils.formats import localize_input, sanitize_separators
|
from django.utils.formats import localize_input, sanitize_separators
|
||||||
from django.utils.ipv6 import clean_ipv6_address
|
from django.utils.ipv6 import clean_ipv6_address
|
||||||
from django.utils.timezone import utc
|
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
from pytz.exceptions import InvalidTimeError
|
from pytz.exceptions import InvalidTimeError
|
||||||
|
|
||||||
|
@ -1190,7 +1189,7 @@ class DateTimeField(Field):
|
||||||
except InvalidTimeError:
|
except InvalidTimeError:
|
||||||
self.fail('make_aware', timezone=field_timezone)
|
self.fail('make_aware', timezone=field_timezone)
|
||||||
elif (field_timezone is None) and timezone.is_aware(value):
|
elif (field_timezone is None) and timezone.is_aware(value):
|
||||||
return timezone.make_naive(value, utc)
|
return timezone.make_naive(value, datetime.timezone.utc)
|
||||||
return value
|
return value
|
||||||
|
|
||||||
def default_timezone(self):
|
def default_timezone(self):
|
||||||
|
|
1
setup.py
|
@ -94,6 +94,7 @@ setup(
|
||||||
'Framework :: Django :: 3.1',
|
'Framework :: Django :: 3.1',
|
||||||
'Framework :: Django :: 3.2',
|
'Framework :: Django :: 3.2',
|
||||||
'Framework :: Django :: 4.0',
|
'Framework :: Django :: 4.0',
|
||||||
|
'Framework :: Django :: 4.1',
|
||||||
'Intended Audience :: Developers',
|
'Intended Audience :: Developers',
|
||||||
'License :: OSI Approved :: BSD License',
|
'License :: OSI Approved :: BSD License',
|
||||||
'Operating System :: OS Independent',
|
'Operating System :: OS Independent',
|
||||||
|
|
|
@ -1,15 +1,16 @@
|
||||||
from datetime import date, datetime, timedelta
|
from datetime import date, datetime, timedelta, timezone
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
from django.utils.timezone import utc
|
|
||||||
|
|
||||||
from rest_framework.compat import coreapi
|
from rest_framework.compat import coreapi
|
||||||
from rest_framework.utils.encoders import JSONEncoder
|
from rest_framework.utils.encoders import JSONEncoder
|
||||||
from rest_framework.utils.serializer_helpers import ReturnList
|
from rest_framework.utils.serializer_helpers import ReturnList
|
||||||
|
|
||||||
|
utc = timezone.utc
|
||||||
|
|
||||||
|
|
||||||
class MockList:
|
class MockList:
|
||||||
def tolist(self):
|
def tolist(self):
|
||||||
|
|
|
@ -9,7 +9,7 @@ import pytz
|
||||||
from django.core.exceptions import ValidationError as DjangoValidationError
|
from django.core.exceptions import ValidationError as DjangoValidationError
|
||||||
from django.http import QueryDict
|
from django.http import QueryDict
|
||||||
from django.test import TestCase, override_settings
|
from django.test import TestCase, override_settings
|
||||||
from django.utils.timezone import activate, deactivate, override, utc
|
from django.utils.timezone import activate, deactivate, override
|
||||||
|
|
||||||
import rest_framework
|
import rest_framework
|
||||||
from rest_framework import exceptions, serializers
|
from rest_framework import exceptions, serializers
|
||||||
|
@ -17,6 +17,8 @@ from rest_framework.fields import (
|
||||||
BuiltinSignatureError, DjangoImageField, is_simple_callable
|
BuiltinSignatureError, DjangoImageField, is_simple_callable
|
||||||
)
|
)
|
||||||
|
|
||||||
|
utc = datetime.timezone.utc
|
||||||
|
|
||||||
# Tests for helper functions.
|
# Tests for helper functions.
|
||||||
# ---------------------------
|
# ---------------------------
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@ import sys
|
||||||
import tempfile
|
import tempfile
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
|
|
||||||
|
import django
|
||||||
import pytest
|
import pytest
|
||||||
from django.core.exceptions import ImproperlyConfigured
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
from django.core.serializers.json import DjangoJSONEncoder
|
from django.core.serializers.json import DjangoJSONEncoder
|
||||||
|
@ -452,11 +453,14 @@ class TestPosgresFieldsMapping(TestCase):
|
||||||
model = ArrayFieldModel
|
model = ArrayFieldModel
|
||||||
fields = ['array_field', 'array_field_with_blank']
|
fields = ['array_field', 'array_field_with_blank']
|
||||||
|
|
||||||
|
validators = ""
|
||||||
|
if django.VERSION < (4, 1):
|
||||||
|
validators = ", validators=[<django.core.validators.MaxLengthValidator object>]"
|
||||||
expected = dedent("""
|
expected = dedent("""
|
||||||
TestSerializer():
|
TestSerializer():
|
||||||
array_field = ListField(allow_empty=False, child=CharField(label='Array field', validators=[<django.core.validators.MaxLengthValidator object>]))
|
array_field = ListField(allow_empty=False, child=CharField(label='Array field'%s))
|
||||||
array_field_with_blank = ListField(child=CharField(label='Array field with blank', validators=[<django.core.validators.MaxLengthValidator object>]), required=False)
|
array_field_with_blank = ListField(child=CharField(label='Array field with blank'%s), required=False)
|
||||||
""")
|
""" % (validators, validators))
|
||||||
self.assertEqual(repr(TestSerializer()), expected)
|
self.assertEqual(repr(TestSerializer()), expected)
|
||||||
|
|
||||||
@pytest.mark.skipif(hasattr(models, 'JSONField'), reason='has models.JSONField')
|
@pytest.mark.skipif(hasattr(models, 'JSONField'), reason='has models.JSONField')
|
||||||
|
|
6
tox.ini
|
@ -3,7 +3,7 @@ envlist =
|
||||||
{py36,py37,py38,py39}-django22,
|
{py36,py37,py38,py39}-django22,
|
||||||
{py36,py37,py38,py39}-django31,
|
{py36,py37,py38,py39}-django31,
|
||||||
{py36,py37,py38,py39,py310}-django32,
|
{py36,py37,py38,py39,py310}-django32,
|
||||||
{py38,py39,py310}-{django40,djangomain},
|
{py38,py39,py310}-{django40,django41,djangomain},
|
||||||
base,dist,docs,
|
base,dist,docs,
|
||||||
|
|
||||||
[travis:env]
|
[travis:env]
|
||||||
|
@ -12,6 +12,7 @@ DJANGO =
|
||||||
3.1: django31
|
3.1: django31
|
||||||
3.2: django32
|
3.2: django32
|
||||||
4.0: django40
|
4.0: django40
|
||||||
|
4.1: django41
|
||||||
main: djangomain
|
main: djangomain
|
||||||
|
|
||||||
[testenv]
|
[testenv]
|
||||||
|
@ -24,7 +25,8 @@ deps =
|
||||||
django22: Django>=2.2,<3.0
|
django22: Django>=2.2,<3.0
|
||||||
django31: Django>=3.1,<3.2
|
django31: Django>=3.1,<3.2
|
||||||
django32: Django>=3.2,<4.0
|
django32: Django>=3.2,<4.0
|
||||||
django40: Django>=4.0,<5.0
|
django40: Django>=4.0,<4.1
|
||||||
|
django41: Django>=4.1a1,<4.2
|
||||||
djangomain: https://github.com/django/django/archive/main.tar.gz
|
djangomain: https://github.com/django/django/archive/main.tar.gz
|
||||||
-rrequirements/requirements-testing.txt
|
-rrequirements/requirements-testing.txt
|
||||||
-rrequirements/requirements-optionals.txt
|
-rrequirements/requirements-optionals.txt
|
||||||
|
|