Initial commit
This commit is contained in:
31
env/lib/python3.10/site-packages/rest_framework/__init__.py
vendored
Normal file
31
env/lib/python3.10/site-packages/rest_framework/__init__.py
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
r"""
|
||||
______ _____ _____ _____ __
|
||||
| ___ \ ___/ ___|_ _| / _| | |
|
||||
| |_/ / |__ \ `--. | | | |_ _ __ __ _ _ __ ___ _____ _____ _ __| |__
|
||||
| /| __| `--. \ | | | _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
|
||||
| |\ \| |___/\__/ / | | | | | | | (_| | | | | | | __/\ V V / (_) | | | <
|
||||
\_| \_\____/\____/ \_/ |_| |_| \__,_|_| |_| |_|\___| \_/\_/ \___/|_| |_|\_|
|
||||
"""
|
||||
|
||||
__title__ = 'Django REST framework'
|
||||
__version__ = '3.15.2'
|
||||
__author__ = 'Tom Christie'
|
||||
__license__ = 'BSD 3-Clause'
|
||||
__copyright__ = 'Copyright 2011-2023 Encode OSS Ltd'
|
||||
|
||||
# Version synonym
|
||||
VERSION = __version__
|
||||
|
||||
# Header encoding (see RFC5987)
|
||||
HTTP_HEADER_ENCODING = 'iso-8859-1'
|
||||
|
||||
# Default datetime input and output formats
|
||||
ISO_8601 = 'iso-8601'
|
||||
|
||||
|
||||
class RemovedInDRF316Warning(DeprecationWarning):
|
||||
pass
|
||||
|
||||
|
||||
class RemovedInDRF317Warning(PendingDeprecationWarning):
|
||||
pass
|
||||
BIN
env/lib/python3.10/site-packages/rest_framework/__pycache__/__init__.cpython-310.pyc
vendored
Normal file
BIN
env/lib/python3.10/site-packages/rest_framework/__pycache__/__init__.cpython-310.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.10/site-packages/rest_framework/__pycache__/apps.cpython-310.pyc
vendored
Normal file
BIN
env/lib/python3.10/site-packages/rest_framework/__pycache__/apps.cpython-310.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.10/site-packages/rest_framework/__pycache__/authentication.cpython-310.pyc
vendored
Normal file
BIN
env/lib/python3.10/site-packages/rest_framework/__pycache__/authentication.cpython-310.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.10/site-packages/rest_framework/__pycache__/checks.cpython-310.pyc
vendored
Normal file
BIN
env/lib/python3.10/site-packages/rest_framework/__pycache__/checks.cpython-310.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.10/site-packages/rest_framework/__pycache__/compat.cpython-310.pyc
vendored
Normal file
BIN
env/lib/python3.10/site-packages/rest_framework/__pycache__/compat.cpython-310.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.10/site-packages/rest_framework/__pycache__/decorators.cpython-310.pyc
vendored
Normal file
BIN
env/lib/python3.10/site-packages/rest_framework/__pycache__/decorators.cpython-310.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.10/site-packages/rest_framework/__pycache__/documentation.cpython-310.pyc
vendored
Normal file
BIN
env/lib/python3.10/site-packages/rest_framework/__pycache__/documentation.cpython-310.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.10/site-packages/rest_framework/__pycache__/exceptions.cpython-310.pyc
vendored
Normal file
BIN
env/lib/python3.10/site-packages/rest_framework/__pycache__/exceptions.cpython-310.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.10/site-packages/rest_framework/__pycache__/fields.cpython-310.pyc
vendored
Normal file
BIN
env/lib/python3.10/site-packages/rest_framework/__pycache__/fields.cpython-310.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.10/site-packages/rest_framework/__pycache__/filters.cpython-310.pyc
vendored
Normal file
BIN
env/lib/python3.10/site-packages/rest_framework/__pycache__/filters.cpython-310.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.10/site-packages/rest_framework/__pycache__/generics.cpython-310.pyc
vendored
Normal file
BIN
env/lib/python3.10/site-packages/rest_framework/__pycache__/generics.cpython-310.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.10/site-packages/rest_framework/__pycache__/metadata.cpython-310.pyc
vendored
Normal file
BIN
env/lib/python3.10/site-packages/rest_framework/__pycache__/metadata.cpython-310.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.10/site-packages/rest_framework/__pycache__/mixins.cpython-310.pyc
vendored
Normal file
BIN
env/lib/python3.10/site-packages/rest_framework/__pycache__/mixins.cpython-310.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.10/site-packages/rest_framework/__pycache__/negotiation.cpython-310.pyc
vendored
Normal file
BIN
env/lib/python3.10/site-packages/rest_framework/__pycache__/negotiation.cpython-310.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.10/site-packages/rest_framework/__pycache__/pagination.cpython-310.pyc
vendored
Normal file
BIN
env/lib/python3.10/site-packages/rest_framework/__pycache__/pagination.cpython-310.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.10/site-packages/rest_framework/__pycache__/parsers.cpython-310.pyc
vendored
Normal file
BIN
env/lib/python3.10/site-packages/rest_framework/__pycache__/parsers.cpython-310.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.10/site-packages/rest_framework/__pycache__/permissions.cpython-310.pyc
vendored
Normal file
BIN
env/lib/python3.10/site-packages/rest_framework/__pycache__/permissions.cpython-310.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.10/site-packages/rest_framework/__pycache__/relations.cpython-310.pyc
vendored
Normal file
BIN
env/lib/python3.10/site-packages/rest_framework/__pycache__/relations.cpython-310.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.10/site-packages/rest_framework/__pycache__/renderers.cpython-310.pyc
vendored
Normal file
BIN
env/lib/python3.10/site-packages/rest_framework/__pycache__/renderers.cpython-310.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.10/site-packages/rest_framework/__pycache__/request.cpython-310.pyc
vendored
Normal file
BIN
env/lib/python3.10/site-packages/rest_framework/__pycache__/request.cpython-310.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.10/site-packages/rest_framework/__pycache__/response.cpython-310.pyc
vendored
Normal file
BIN
env/lib/python3.10/site-packages/rest_framework/__pycache__/response.cpython-310.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.10/site-packages/rest_framework/__pycache__/reverse.cpython-310.pyc
vendored
Normal file
BIN
env/lib/python3.10/site-packages/rest_framework/__pycache__/reverse.cpython-310.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.10/site-packages/rest_framework/__pycache__/routers.cpython-310.pyc
vendored
Normal file
BIN
env/lib/python3.10/site-packages/rest_framework/__pycache__/routers.cpython-310.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.10/site-packages/rest_framework/__pycache__/serializers.cpython-310.pyc
vendored
Normal file
BIN
env/lib/python3.10/site-packages/rest_framework/__pycache__/serializers.cpython-310.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.10/site-packages/rest_framework/__pycache__/settings.cpython-310.pyc
vendored
Normal file
BIN
env/lib/python3.10/site-packages/rest_framework/__pycache__/settings.cpython-310.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.10/site-packages/rest_framework/__pycache__/status.cpython-310.pyc
vendored
Normal file
BIN
env/lib/python3.10/site-packages/rest_framework/__pycache__/status.cpython-310.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.10/site-packages/rest_framework/__pycache__/test.cpython-310.pyc
vendored
Normal file
BIN
env/lib/python3.10/site-packages/rest_framework/__pycache__/test.cpython-310.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.10/site-packages/rest_framework/__pycache__/throttling.cpython-310.pyc
vendored
Normal file
BIN
env/lib/python3.10/site-packages/rest_framework/__pycache__/throttling.cpython-310.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.10/site-packages/rest_framework/__pycache__/urlpatterns.cpython-310.pyc
vendored
Normal file
BIN
env/lib/python3.10/site-packages/rest_framework/__pycache__/urlpatterns.cpython-310.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.10/site-packages/rest_framework/__pycache__/urls.cpython-310.pyc
vendored
Normal file
BIN
env/lib/python3.10/site-packages/rest_framework/__pycache__/urls.cpython-310.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.10/site-packages/rest_framework/__pycache__/validators.cpython-310.pyc
vendored
Normal file
BIN
env/lib/python3.10/site-packages/rest_framework/__pycache__/validators.cpython-310.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.10/site-packages/rest_framework/__pycache__/versioning.cpython-310.pyc
vendored
Normal file
BIN
env/lib/python3.10/site-packages/rest_framework/__pycache__/versioning.cpython-310.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.10/site-packages/rest_framework/__pycache__/views.cpython-310.pyc
vendored
Normal file
BIN
env/lib/python3.10/site-packages/rest_framework/__pycache__/views.cpython-310.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.10/site-packages/rest_framework/__pycache__/viewsets.cpython-310.pyc
vendored
Normal file
BIN
env/lib/python3.10/site-packages/rest_framework/__pycache__/viewsets.cpython-310.pyc
vendored
Normal file
Binary file not shown.
10
env/lib/python3.10/site-packages/rest_framework/apps.py
vendored
Normal file
10
env/lib/python3.10/site-packages/rest_framework/apps.py
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class RestFrameworkConfig(AppConfig):
|
||||
name = 'rest_framework'
|
||||
verbose_name = "Django REST framework"
|
||||
|
||||
def ready(self):
|
||||
# Add System checks
|
||||
from .checks import pagination_system_check # NOQA
|
||||
232
env/lib/python3.10/site-packages/rest_framework/authentication.py
vendored
Normal file
232
env/lib/python3.10/site-packages/rest_framework/authentication.py
vendored
Normal file
@@ -0,0 +1,232 @@
|
||||
"""
|
||||
Provides various authentication policies.
|
||||
"""
|
||||
import base64
|
||||
import binascii
|
||||
|
||||
from django.contrib.auth import authenticate, get_user_model
|
||||
from django.middleware.csrf import CsrfViewMiddleware
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from rest_framework import HTTP_HEADER_ENCODING, exceptions
|
||||
|
||||
|
||||
def get_authorization_header(request):
|
||||
"""
|
||||
Return request's 'Authorization:' header, as a bytestring.
|
||||
|
||||
Hide some test client ickyness where the header can be unicode.
|
||||
"""
|
||||
auth = request.META.get('HTTP_AUTHORIZATION', b'')
|
||||
if isinstance(auth, str):
|
||||
# Work around django test client oddness
|
||||
auth = auth.encode(HTTP_HEADER_ENCODING)
|
||||
return auth
|
||||
|
||||
|
||||
class CSRFCheck(CsrfViewMiddleware):
|
||||
def _reject(self, request, reason):
|
||||
# Return the failure reason instead of an HttpResponse
|
||||
return reason
|
||||
|
||||
|
||||
class BaseAuthentication:
|
||||
"""
|
||||
All authentication classes should extend BaseAuthentication.
|
||||
"""
|
||||
|
||||
def authenticate(self, request):
|
||||
"""
|
||||
Authenticate the request and return a two-tuple of (user, token).
|
||||
"""
|
||||
raise NotImplementedError(".authenticate() must be overridden.")
|
||||
|
||||
def authenticate_header(self, request):
|
||||
"""
|
||||
Return a string to be used as the value of the `WWW-Authenticate`
|
||||
header in a `401 Unauthenticated` response, or `None` if the
|
||||
authentication scheme should return `403 Permission Denied` responses.
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
class BasicAuthentication(BaseAuthentication):
|
||||
"""
|
||||
HTTP Basic authentication against username/password.
|
||||
"""
|
||||
www_authenticate_realm = 'api'
|
||||
|
||||
def authenticate(self, request):
|
||||
"""
|
||||
Returns a `User` if a correct username and password have been supplied
|
||||
using HTTP Basic authentication. Otherwise returns `None`.
|
||||
"""
|
||||
auth = get_authorization_header(request).split()
|
||||
|
||||
if not auth or auth[0].lower() != b'basic':
|
||||
return None
|
||||
|
||||
if len(auth) == 1:
|
||||
msg = _('Invalid basic header. No credentials provided.')
|
||||
raise exceptions.AuthenticationFailed(msg)
|
||||
elif len(auth) > 2:
|
||||
msg = _('Invalid basic header. Credentials string should not contain spaces.')
|
||||
raise exceptions.AuthenticationFailed(msg)
|
||||
|
||||
try:
|
||||
try:
|
||||
auth_decoded = base64.b64decode(auth[1]).decode('utf-8')
|
||||
except UnicodeDecodeError:
|
||||
auth_decoded = base64.b64decode(auth[1]).decode('latin-1')
|
||||
|
||||
userid, password = auth_decoded.split(':', 1)
|
||||
except (TypeError, ValueError, UnicodeDecodeError, binascii.Error):
|
||||
msg = _('Invalid basic header. Credentials not correctly base64 encoded.')
|
||||
raise exceptions.AuthenticationFailed(msg)
|
||||
|
||||
return self.authenticate_credentials(userid, password, request)
|
||||
|
||||
def authenticate_credentials(self, userid, password, request=None):
|
||||
"""
|
||||
Authenticate the userid and password against username and password
|
||||
with optional request for context.
|
||||
"""
|
||||
credentials = {
|
||||
get_user_model().USERNAME_FIELD: userid,
|
||||
'password': password
|
||||
}
|
||||
user = authenticate(request=request, **credentials)
|
||||
|
||||
if user is None:
|
||||
raise exceptions.AuthenticationFailed(_('Invalid username/password.'))
|
||||
|
||||
if not user.is_active:
|
||||
raise exceptions.AuthenticationFailed(_('User inactive or deleted.'))
|
||||
|
||||
return (user, None)
|
||||
|
||||
def authenticate_header(self, request):
|
||||
return 'Basic realm="%s"' % self.www_authenticate_realm
|
||||
|
||||
|
||||
class SessionAuthentication(BaseAuthentication):
|
||||
"""
|
||||
Use Django's session framework for authentication.
|
||||
"""
|
||||
|
||||
def authenticate(self, request):
|
||||
"""
|
||||
Returns a `User` if the request session currently has a logged in user.
|
||||
Otherwise returns `None`.
|
||||
"""
|
||||
|
||||
# Get the session-based user from the underlying HttpRequest object
|
||||
user = getattr(request._request, 'user', None)
|
||||
|
||||
# Unauthenticated, CSRF validation not required
|
||||
if not user or not user.is_active:
|
||||
return None
|
||||
|
||||
self.enforce_csrf(request)
|
||||
|
||||
# CSRF passed with authenticated user
|
||||
return (user, None)
|
||||
|
||||
def enforce_csrf(self, request):
|
||||
"""
|
||||
Enforce CSRF validation for session based authentication.
|
||||
"""
|
||||
def dummy_get_response(request): # pragma: no cover
|
||||
return None
|
||||
|
||||
check = CSRFCheck(dummy_get_response)
|
||||
# populates request.META['CSRF_COOKIE'], which is used in process_view()
|
||||
check.process_request(request)
|
||||
reason = check.process_view(request, None, (), {})
|
||||
if reason:
|
||||
# CSRF failed, bail with explicit error message
|
||||
raise exceptions.PermissionDenied('CSRF Failed: %s' % reason)
|
||||
|
||||
|
||||
class TokenAuthentication(BaseAuthentication):
|
||||
"""
|
||||
Simple token based authentication.
|
||||
|
||||
Clients should authenticate by passing the token key in the "Authorization"
|
||||
HTTP header, prepended with the string "Token ". For example:
|
||||
|
||||
Authorization: Token 401f7ac837da42b97f613d789819ff93537bee6a
|
||||
"""
|
||||
|
||||
keyword = 'Token'
|
||||
model = None
|
||||
|
||||
def get_model(self):
|
||||
if self.model is not None:
|
||||
return self.model
|
||||
from rest_framework.authtoken.models import Token
|
||||
return Token
|
||||
|
||||
"""
|
||||
A custom token model may be used, but must have the following properties.
|
||||
|
||||
* key -- The string identifying the token
|
||||
* user -- The user to which the token belongs
|
||||
"""
|
||||
|
||||
def authenticate(self, request):
|
||||
auth = get_authorization_header(request).split()
|
||||
|
||||
if not auth or auth[0].lower() != self.keyword.lower().encode():
|
||||
return None
|
||||
|
||||
if len(auth) == 1:
|
||||
msg = _('Invalid token header. No credentials provided.')
|
||||
raise exceptions.AuthenticationFailed(msg)
|
||||
elif len(auth) > 2:
|
||||
msg = _('Invalid token header. Token string should not contain spaces.')
|
||||
raise exceptions.AuthenticationFailed(msg)
|
||||
|
||||
try:
|
||||
token = auth[1].decode()
|
||||
except UnicodeError:
|
||||
msg = _('Invalid token header. Token string should not contain invalid characters.')
|
||||
raise exceptions.AuthenticationFailed(msg)
|
||||
|
||||
return self.authenticate_credentials(token)
|
||||
|
||||
def authenticate_credentials(self, key):
|
||||
model = self.get_model()
|
||||
try:
|
||||
token = model.objects.select_related('user').get(key=key)
|
||||
except model.DoesNotExist:
|
||||
raise exceptions.AuthenticationFailed(_('Invalid token.'))
|
||||
|
||||
if not token.user.is_active:
|
||||
raise exceptions.AuthenticationFailed(_('User inactive or deleted.'))
|
||||
|
||||
return (token.user, token)
|
||||
|
||||
def authenticate_header(self, request):
|
||||
return self.keyword
|
||||
|
||||
|
||||
class RemoteUserAuthentication(BaseAuthentication):
|
||||
"""
|
||||
REMOTE_USER authentication.
|
||||
|
||||
To use this, set up your web server to perform authentication, which will
|
||||
set the REMOTE_USER environment variable. You will need to have
|
||||
'django.contrib.auth.backends.RemoteUserBackend in your
|
||||
AUTHENTICATION_BACKENDS setting
|
||||
"""
|
||||
|
||||
# Name of request header to grab username from. This will be the key as
|
||||
# used in the request.META dictionary, i.e. the normalization of headers to
|
||||
# all uppercase and the addition of "HTTP_" prefix apply.
|
||||
header = "REMOTE_USER"
|
||||
|
||||
def authenticate(self, request):
|
||||
user = authenticate(request=request, remote_user=request.META.get(self.header))
|
||||
if user and user.is_active:
|
||||
return (user, None)
|
||||
0
env/lib/python3.10/site-packages/rest_framework/authtoken/__init__.py
vendored
Normal file
0
env/lib/python3.10/site-packages/rest_framework/authtoken/__init__.py
vendored
Normal file
BIN
env/lib/python3.10/site-packages/rest_framework/authtoken/__pycache__/__init__.cpython-310.pyc
vendored
Normal file
BIN
env/lib/python3.10/site-packages/rest_framework/authtoken/__pycache__/__init__.cpython-310.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.10/site-packages/rest_framework/authtoken/__pycache__/admin.cpython-310.pyc
vendored
Normal file
BIN
env/lib/python3.10/site-packages/rest_framework/authtoken/__pycache__/admin.cpython-310.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.10/site-packages/rest_framework/authtoken/__pycache__/apps.cpython-310.pyc
vendored
Normal file
BIN
env/lib/python3.10/site-packages/rest_framework/authtoken/__pycache__/apps.cpython-310.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.10/site-packages/rest_framework/authtoken/__pycache__/models.cpython-310.pyc
vendored
Normal file
BIN
env/lib/python3.10/site-packages/rest_framework/authtoken/__pycache__/models.cpython-310.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.10/site-packages/rest_framework/authtoken/__pycache__/serializers.cpython-310.pyc
vendored
Normal file
BIN
env/lib/python3.10/site-packages/rest_framework/authtoken/__pycache__/serializers.cpython-310.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.10/site-packages/rest_framework/authtoken/__pycache__/views.cpython-310.pyc
vendored
Normal file
BIN
env/lib/python3.10/site-packages/rest_framework/authtoken/__pycache__/views.cpython-310.pyc
vendored
Normal file
Binary file not shown.
54
env/lib/python3.10/site-packages/rest_framework/authtoken/admin.py
vendored
Normal file
54
env/lib/python3.10/site-packages/rest_framework/authtoken/admin.py
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
from django.contrib import admin
|
||||
from django.contrib.admin.utils import quote
|
||||
from django.contrib.admin.views.main import ChangeList
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.urls import reverse
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from rest_framework.authtoken.models import Token, TokenProxy
|
||||
|
||||
User = get_user_model()
|
||||
|
||||
|
||||
class TokenChangeList(ChangeList):
|
||||
"""Map to matching User id"""
|
||||
def url_for_result(self, result):
|
||||
pk = result.user.pk
|
||||
return reverse('admin:%s_%s_change' % (self.opts.app_label,
|
||||
self.opts.model_name),
|
||||
args=(quote(pk),),
|
||||
current_app=self.model_admin.admin_site.name)
|
||||
|
||||
|
||||
class TokenAdmin(admin.ModelAdmin):
|
||||
list_display = ('key', 'user', 'created')
|
||||
fields = ('user',)
|
||||
search_fields = ('user__username',)
|
||||
search_help_text = _('Username')
|
||||
ordering = ('-created',)
|
||||
actions = None # Actions not compatible with mapped IDs.
|
||||
|
||||
def get_changelist(self, request, **kwargs):
|
||||
return TokenChangeList
|
||||
|
||||
def get_object(self, request, object_id, from_field=None):
|
||||
"""
|
||||
Map from User ID to matching Token.
|
||||
"""
|
||||
queryset = self.get_queryset(request)
|
||||
field = User._meta.pk
|
||||
try:
|
||||
object_id = field.to_python(object_id)
|
||||
user = User.objects.get(**{field.name: object_id})
|
||||
return queryset.get(user=user)
|
||||
except (queryset.model.DoesNotExist, User.DoesNotExist, ValidationError, ValueError):
|
||||
return None
|
||||
|
||||
def delete_model(self, request, obj):
|
||||
# Map back to actual Token, since delete() uses pk.
|
||||
token = Token.objects.get(key=obj.key)
|
||||
return super().delete_model(request, token)
|
||||
|
||||
|
||||
admin.site.register(TokenProxy, TokenAdmin)
|
||||
7
env/lib/python3.10/site-packages/rest_framework/authtoken/apps.py
vendored
Normal file
7
env/lib/python3.10/site-packages/rest_framework/authtoken/apps.py
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
from django.apps import AppConfig
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
|
||||
class AuthTokenConfig(AppConfig):
|
||||
name = 'rest_framework.authtoken'
|
||||
verbose_name = _("Auth Token")
|
||||
0
env/lib/python3.10/site-packages/rest_framework/authtoken/management/__init__.py
vendored
Normal file
0
env/lib/python3.10/site-packages/rest_framework/authtoken/management/__init__.py
vendored
Normal file
Binary file not shown.
0
env/lib/python3.10/site-packages/rest_framework/authtoken/management/commands/__init__.py
vendored
Normal file
0
env/lib/python3.10/site-packages/rest_framework/authtoken/management/commands/__init__.py
vendored
Normal file
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,45 @@
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.core.management.base import BaseCommand, CommandError
|
||||
|
||||
from rest_framework.authtoken.models import Token
|
||||
|
||||
UserModel = get_user_model()
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = 'Create DRF Token for a given user'
|
||||
|
||||
def create_user_token(self, username, reset_token):
|
||||
user = UserModel._default_manager.get_by_natural_key(username)
|
||||
|
||||
if reset_token:
|
||||
Token.objects.filter(user=user).delete()
|
||||
|
||||
token = Token.objects.get_or_create(user=user)
|
||||
return token[0]
|
||||
|
||||
def add_arguments(self, parser):
|
||||
parser.add_argument('username', type=str)
|
||||
|
||||
parser.add_argument(
|
||||
'-r',
|
||||
'--reset',
|
||||
action='store_true',
|
||||
dest='reset_token',
|
||||
default=False,
|
||||
help='Reset existing User token and create a new one',
|
||||
)
|
||||
|
||||
def handle(self, *args, **options):
|
||||
username = options['username']
|
||||
reset_token = options['reset_token']
|
||||
|
||||
try:
|
||||
token = self.create_user_token(username, reset_token)
|
||||
except UserModel.DoesNotExist:
|
||||
raise CommandError(
|
||||
'Cannot create the Token: user {} does not exist'.format(
|
||||
username)
|
||||
)
|
||||
self.stdout.write(
|
||||
'Generated token {} for user {}'.format(token.key, username))
|
||||
23
env/lib/python3.10/site-packages/rest_framework/authtoken/migrations/0001_initial.py
vendored
Normal file
23
env/lib/python3.10/site-packages/rest_framework/authtoken/migrations/0001_initial.py
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Token',
|
||||
fields=[
|
||||
('key', models.CharField(primary_key=True, serialize=False, max_length=40)),
|
||||
('created', models.DateTimeField(auto_now_add=True)),
|
||||
('user', models.OneToOneField(to=settings.AUTH_USER_MODEL, related_name='auth_token', on_delete=models.CASCADE)),
|
||||
],
|
||||
options={
|
||||
},
|
||||
bases=(models.Model,),
|
||||
),
|
||||
]
|
||||
31
env/lib/python3.10/site-packages/rest_framework/authtoken/migrations/0002_auto_20160226_1747.py
vendored
Normal file
31
env/lib/python3.10/site-packages/rest_framework/authtoken/migrations/0002_auto_20160226_1747.py
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('authtoken', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='token',
|
||||
options={'verbose_name_plural': 'Tokens', 'verbose_name': 'Token'},
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='token',
|
||||
name='created',
|
||||
field=models.DateTimeField(verbose_name='Created', auto_now_add=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='token',
|
||||
name='key',
|
||||
field=models.CharField(verbose_name='Key', max_length=40, primary_key=True, serialize=False),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='token',
|
||||
name='user',
|
||||
field=models.OneToOneField(to=settings.AUTH_USER_MODEL, verbose_name='User', related_name='auth_token', on_delete=models.CASCADE),
|
||||
),
|
||||
]
|
||||
25
env/lib/python3.10/site-packages/rest_framework/authtoken/migrations/0003_tokenproxy.py
vendored
Normal file
25
env/lib/python3.10/site-packages/rest_framework/authtoken/migrations/0003_tokenproxy.py
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
# Generated by Django 3.1.1 on 2020-09-28 09:34
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('authtoken', '0002_auto_20160226_1747'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='TokenProxy',
|
||||
fields=[
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'token',
|
||||
'proxy': True,
|
||||
'indexes': [],
|
||||
'constraints': [],
|
||||
},
|
||||
bases=('authtoken.token',),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,17 @@
|
||||
# Generated by Django 4.1.3 on 2022-11-24 21:07
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('authtoken', '0003_tokenproxy'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='tokenproxy',
|
||||
options={'verbose_name': 'Token', 'verbose_name_plural': 'Tokens'},
|
||||
),
|
||||
]
|
||||
0
env/lib/python3.10/site-packages/rest_framework/authtoken/migrations/__init__.py
vendored
Normal file
0
env/lib/python3.10/site-packages/rest_framework/authtoken/migrations/__init__.py
vendored
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
55
env/lib/python3.10/site-packages/rest_framework/authtoken/models.py
vendored
Normal file
55
env/lib/python3.10/site-packages/rest_framework/authtoken/models.py
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
import binascii
|
||||
import os
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import models
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
|
||||
class Token(models.Model):
|
||||
"""
|
||||
The default authorization token model.
|
||||
"""
|
||||
key = models.CharField(_("Key"), max_length=40, primary_key=True)
|
||||
user = models.OneToOneField(
|
||||
settings.AUTH_USER_MODEL, related_name='auth_token',
|
||||
on_delete=models.CASCADE, verbose_name=_("User")
|
||||
)
|
||||
created = models.DateTimeField(_("Created"), auto_now_add=True)
|
||||
|
||||
class Meta:
|
||||
# Work around for a bug in Django:
|
||||
# https://code.djangoproject.com/ticket/19422
|
||||
#
|
||||
# Also see corresponding ticket:
|
||||
# https://github.com/encode/django-rest-framework/issues/705
|
||||
abstract = 'rest_framework.authtoken' not in settings.INSTALLED_APPS
|
||||
verbose_name = _("Token")
|
||||
verbose_name_plural = _("Tokens")
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
if not self.key:
|
||||
self.key = self.generate_key()
|
||||
return super().save(*args, **kwargs)
|
||||
|
||||
@classmethod
|
||||
def generate_key(cls):
|
||||
return binascii.hexlify(os.urandom(20)).decode()
|
||||
|
||||
def __str__(self):
|
||||
return self.key
|
||||
|
||||
|
||||
class TokenProxy(Token):
|
||||
"""
|
||||
Proxy mapping pk to user pk for use in admin.
|
||||
"""
|
||||
@property
|
||||
def pk(self):
|
||||
return self.user_id
|
||||
|
||||
class Meta:
|
||||
proxy = 'rest_framework.authtoken' in settings.INSTALLED_APPS
|
||||
abstract = 'rest_framework.authtoken' not in settings.INSTALLED_APPS
|
||||
verbose_name = _("Token")
|
||||
verbose_name_plural = _("Tokens")
|
||||
42
env/lib/python3.10/site-packages/rest_framework/authtoken/serializers.py
vendored
Normal file
42
env/lib/python3.10/site-packages/rest_framework/authtoken/serializers.py
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
from django.contrib.auth import authenticate
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from rest_framework import serializers
|
||||
|
||||
|
||||
class AuthTokenSerializer(serializers.Serializer):
|
||||
username = serializers.CharField(
|
||||
label=_("Username"),
|
||||
write_only=True
|
||||
)
|
||||
password = serializers.CharField(
|
||||
label=_("Password"),
|
||||
style={'input_type': 'password'},
|
||||
trim_whitespace=False,
|
||||
write_only=True
|
||||
)
|
||||
token = serializers.CharField(
|
||||
label=_("Token"),
|
||||
read_only=True
|
||||
)
|
||||
|
||||
def validate(self, attrs):
|
||||
username = attrs.get('username')
|
||||
password = attrs.get('password')
|
||||
|
||||
if username and password:
|
||||
user = authenticate(request=self.context.get('request'),
|
||||
username=username, password=password)
|
||||
|
||||
# The authenticate call simply returns None for is_active=False
|
||||
# users. (Assuming the default ModelBackend authentication
|
||||
# backend.)
|
||||
if not user:
|
||||
msg = _('Unable to log in with provided credentials.')
|
||||
raise serializers.ValidationError(msg, code='authorization')
|
||||
else:
|
||||
msg = _('Must include "username" and "password".')
|
||||
raise serializers.ValidationError(msg, code='authorization')
|
||||
|
||||
attrs['user'] = user
|
||||
return attrs
|
||||
62
env/lib/python3.10/site-packages/rest_framework/authtoken/views.py
vendored
Normal file
62
env/lib/python3.10/site-packages/rest_framework/authtoken/views.py
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
from rest_framework import parsers, renderers
|
||||
from rest_framework.authtoken.models import Token
|
||||
from rest_framework.authtoken.serializers import AuthTokenSerializer
|
||||
from rest_framework.compat import coreapi, coreschema
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.schemas import ManualSchema
|
||||
from rest_framework.schemas import coreapi as coreapi_schema
|
||||
from rest_framework.views import APIView
|
||||
|
||||
|
||||
class ObtainAuthToken(APIView):
|
||||
throttle_classes = ()
|
||||
permission_classes = ()
|
||||
parser_classes = (parsers.FormParser, parsers.MultiPartParser, parsers.JSONParser,)
|
||||
renderer_classes = (renderers.JSONRenderer,)
|
||||
serializer_class = AuthTokenSerializer
|
||||
|
||||
if coreapi_schema.is_enabled():
|
||||
schema = ManualSchema(
|
||||
fields=[
|
||||
coreapi.Field(
|
||||
name="username",
|
||||
required=True,
|
||||
location='form',
|
||||
schema=coreschema.String(
|
||||
title="Username",
|
||||
description="Valid username for authentication",
|
||||
),
|
||||
),
|
||||
coreapi.Field(
|
||||
name="password",
|
||||
required=True,
|
||||
location='form',
|
||||
schema=coreschema.String(
|
||||
title="Password",
|
||||
description="Valid password for authentication",
|
||||
),
|
||||
),
|
||||
],
|
||||
encoding="application/json",
|
||||
)
|
||||
|
||||
def get_serializer_context(self):
|
||||
return {
|
||||
'request': self.request,
|
||||
'format': self.format_kwarg,
|
||||
'view': self
|
||||
}
|
||||
|
||||
def get_serializer(self, *args, **kwargs):
|
||||
kwargs['context'] = self.get_serializer_context()
|
||||
return self.serializer_class(*args, **kwargs)
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
serializer = self.get_serializer(data=request.data)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
user = serializer.validated_data['user']
|
||||
token, created = Token.objects.get_or_create(user=user)
|
||||
return Response({'token': token.key})
|
||||
|
||||
|
||||
obtain_auth_token = ObtainAuthToken.as_view()
|
||||
21
env/lib/python3.10/site-packages/rest_framework/checks.py
vendored
Normal file
21
env/lib/python3.10/site-packages/rest_framework/checks.py
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
from django.core.checks import Tags, Warning, register
|
||||
|
||||
|
||||
@register(Tags.compatibility)
|
||||
def pagination_system_check(app_configs, **kwargs):
|
||||
errors = []
|
||||
# Use of default page size setting requires a default Paginator class
|
||||
from rest_framework.settings import api_settings
|
||||
if api_settings.PAGE_SIZE and not api_settings.DEFAULT_PAGINATION_CLASS:
|
||||
errors.append(
|
||||
Warning(
|
||||
"You have specified a default PAGE_SIZE pagination rest_framework setting, "
|
||||
"without specifying also a DEFAULT_PAGINATION_CLASS.",
|
||||
hint="The default for DEFAULT_PAGINATION_CLASS is None. "
|
||||
"In previous versions this was PageNumberPagination. "
|
||||
"If you wish to define PAGE_SIZE globally whilst defining "
|
||||
"pagination_class on a per-view basis you may silence this check.",
|
||||
id="rest_framework.W001"
|
||||
)
|
||||
)
|
||||
return errors
|
||||
173
env/lib/python3.10/site-packages/rest_framework/compat.py
vendored
Normal file
173
env/lib/python3.10/site-packages/rest_framework/compat.py
vendored
Normal file
@@ -0,0 +1,173 @@
|
||||
"""
|
||||
The `compat` module provides support for backwards compatibility with older
|
||||
versions of Django/Python, and compatibility wrappers around optional packages.
|
||||
"""
|
||||
import django
|
||||
from django.views.generic import View
|
||||
|
||||
|
||||
def unicode_http_header(value):
|
||||
# Coerce HTTP header value to unicode.
|
||||
if isinstance(value, bytes):
|
||||
return value.decode('iso-8859-1')
|
||||
return value
|
||||
|
||||
|
||||
# django.contrib.postgres requires psycopg2
|
||||
try:
|
||||
from django.contrib.postgres import fields as postgres_fields
|
||||
except ImportError:
|
||||
postgres_fields = None
|
||||
|
||||
|
||||
# coreapi is required for CoreAPI schema generation
|
||||
try:
|
||||
import coreapi
|
||||
except ImportError:
|
||||
coreapi = None
|
||||
|
||||
# uritemplate is required for OpenAPI and CoreAPI schema generation
|
||||
try:
|
||||
import uritemplate
|
||||
except ImportError:
|
||||
uritemplate = None
|
||||
|
||||
|
||||
# coreschema is optional
|
||||
try:
|
||||
import coreschema
|
||||
except ImportError:
|
||||
coreschema = None
|
||||
|
||||
|
||||
# pyyaml is optional
|
||||
try:
|
||||
import yaml
|
||||
except ImportError:
|
||||
yaml = None
|
||||
|
||||
# inflection is optional
|
||||
try:
|
||||
import inflection
|
||||
except ImportError:
|
||||
inflection = None
|
||||
|
||||
|
||||
# requests is optional
|
||||
try:
|
||||
import requests
|
||||
except ImportError:
|
||||
requests = None
|
||||
|
||||
|
||||
# PATCH method is not implemented by Django
|
||||
if 'patch' not in View.http_method_names:
|
||||
View.http_method_names = View.http_method_names + ['patch']
|
||||
|
||||
|
||||
# Markdown is optional (version 3.0+ required)
|
||||
try:
|
||||
import markdown
|
||||
|
||||
HEADERID_EXT_PATH = 'markdown.extensions.toc'
|
||||
LEVEL_PARAM = 'baselevel'
|
||||
|
||||
def apply_markdown(text):
|
||||
"""
|
||||
Simple wrapper around :func:`markdown.markdown` to set the base level
|
||||
of '#' style headers to <h2>.
|
||||
"""
|
||||
extensions = [HEADERID_EXT_PATH]
|
||||
extension_configs = {
|
||||
HEADERID_EXT_PATH: {
|
||||
LEVEL_PARAM: '2'
|
||||
}
|
||||
}
|
||||
md = markdown.Markdown(
|
||||
extensions=extensions, extension_configs=extension_configs
|
||||
)
|
||||
md_filter_add_syntax_highlight(md)
|
||||
return md.convert(text)
|
||||
except ImportError:
|
||||
apply_markdown = None
|
||||
markdown = None
|
||||
|
||||
|
||||
try:
|
||||
import pygments
|
||||
from pygments.formatters import HtmlFormatter
|
||||
from pygments.lexers import TextLexer, get_lexer_by_name
|
||||
|
||||
def pygments_highlight(text, lang, style):
|
||||
lexer = get_lexer_by_name(lang, stripall=False)
|
||||
formatter = HtmlFormatter(nowrap=True, style=style)
|
||||
return pygments.highlight(text, lexer, formatter)
|
||||
|
||||
def pygments_css(style):
|
||||
formatter = HtmlFormatter(style=style)
|
||||
return formatter.get_style_defs('.highlight')
|
||||
|
||||
except ImportError:
|
||||
pygments = None
|
||||
|
||||
def pygments_highlight(text, lang, style):
|
||||
return text
|
||||
|
||||
def pygments_css(style):
|
||||
return None
|
||||
|
||||
if markdown is not None and pygments is not None:
|
||||
# starting from this blogpost and modified to support current markdown extensions API
|
||||
# https://zerokspot.com/weblog/2008/06/18/syntax-highlighting-in-markdown-with-pygments/
|
||||
|
||||
import re
|
||||
|
||||
from markdown.preprocessors import Preprocessor
|
||||
|
||||
class CodeBlockPreprocessor(Preprocessor):
|
||||
pattern = re.compile(
|
||||
r'^\s*``` *([^\n]+)\n(.+?)^\s*```', re.M | re.S)
|
||||
|
||||
formatter = HtmlFormatter()
|
||||
|
||||
def run(self, lines):
|
||||
def repl(m):
|
||||
try:
|
||||
lexer = get_lexer_by_name(m.group(1))
|
||||
except (ValueError, NameError):
|
||||
lexer = TextLexer()
|
||||
code = m.group(2).replace('\t', ' ')
|
||||
code = pygments.highlight(code, lexer, self.formatter)
|
||||
code = code.replace('\n\n', '\n \n').replace('\n', '<br />').replace('\\@', '@')
|
||||
return '\n\n%s\n\n' % code
|
||||
ret = self.pattern.sub(repl, "\n".join(lines))
|
||||
return ret.split("\n")
|
||||
|
||||
def md_filter_add_syntax_highlight(md):
|
||||
md.preprocessors.register(CodeBlockPreprocessor(), 'highlight', 40)
|
||||
return True
|
||||
else:
|
||||
def md_filter_add_syntax_highlight(md):
|
||||
return False
|
||||
|
||||
|
||||
if django.VERSION >= (5, 1):
|
||||
# Django 5.1+: use the stock ip_address_validators function
|
||||
# Note: Before Django 5.1, ip_address_validators returns a tuple containing
|
||||
# 1) the list of validators and 2) the error message. Starting from
|
||||
# Django 5.1 ip_address_validators only returns the list of validators
|
||||
from django.core.validators import ip_address_validators
|
||||
else:
|
||||
# Django <= 5.1: create a compatibility shim for ip_address_validators
|
||||
from django.core.validators import \
|
||||
ip_address_validators as _ip_address_validators
|
||||
|
||||
def ip_address_validators(protocol, unpack_ipv4):
|
||||
return _ip_address_validators(protocol, unpack_ipv4)[0]
|
||||
|
||||
|
||||
# `separators` argument to `json.dumps()` differs between 2.x and 3.x
|
||||
# See: https://bugs.python.org/issue22767
|
||||
SHORT_SEPARATORS = (',', ':')
|
||||
LONG_SEPARATORS = (', ', ': ')
|
||||
INDENT_SEPARATORS = (',', ': ')
|
||||
233
env/lib/python3.10/site-packages/rest_framework/decorators.py
vendored
Normal file
233
env/lib/python3.10/site-packages/rest_framework/decorators.py
vendored
Normal file
@@ -0,0 +1,233 @@
|
||||
"""
|
||||
The most important decorator in this module is `@api_view`, which is used
|
||||
for writing function-based views with REST framework.
|
||||
|
||||
There are also various decorators for setting the API policies on function
|
||||
based views, as well as the `@action` decorator, which is used to annotate
|
||||
methods on viewsets that should be included by routers.
|
||||
"""
|
||||
import types
|
||||
|
||||
from django.forms.utils import pretty_name
|
||||
|
||||
from rest_framework.views import APIView
|
||||
|
||||
|
||||
def api_view(http_method_names=None):
|
||||
"""
|
||||
Decorator that converts a function-based view into an APIView subclass.
|
||||
Takes a list of allowed methods for the view as an argument.
|
||||
"""
|
||||
http_method_names = ['GET'] if (http_method_names is None) else http_method_names
|
||||
|
||||
def decorator(func):
|
||||
|
||||
WrappedAPIView = type(
|
||||
'WrappedAPIView',
|
||||
(APIView,),
|
||||
{'__doc__': func.__doc__}
|
||||
)
|
||||
|
||||
# Note, the above allows us to set the docstring.
|
||||
# It is the equivalent of:
|
||||
#
|
||||
# class WrappedAPIView(APIView):
|
||||
# pass
|
||||
# WrappedAPIView.__doc__ = func.doc <--- Not possible to do this
|
||||
|
||||
# api_view applied without (method_names)
|
||||
assert not isinstance(http_method_names, types.FunctionType), \
|
||||
'@api_view missing list of allowed HTTP methods'
|
||||
|
||||
# api_view applied with eg. string instead of list of strings
|
||||
assert isinstance(http_method_names, (list, tuple)), \
|
||||
'@api_view expected a list of strings, received %s' % type(http_method_names).__name__
|
||||
|
||||
allowed_methods = set(http_method_names) | {'options'}
|
||||
WrappedAPIView.http_method_names = [method.lower() for method in allowed_methods]
|
||||
|
||||
def handler(self, *args, **kwargs):
|
||||
return func(*args, **kwargs)
|
||||
|
||||
for method in http_method_names:
|
||||
setattr(WrappedAPIView, method.lower(), handler)
|
||||
|
||||
WrappedAPIView.__name__ = func.__name__
|
||||
WrappedAPIView.__module__ = func.__module__
|
||||
|
||||
WrappedAPIView.renderer_classes = getattr(func, 'renderer_classes',
|
||||
APIView.renderer_classes)
|
||||
|
||||
WrappedAPIView.parser_classes = getattr(func, 'parser_classes',
|
||||
APIView.parser_classes)
|
||||
|
||||
WrappedAPIView.authentication_classes = getattr(func, 'authentication_classes',
|
||||
APIView.authentication_classes)
|
||||
|
||||
WrappedAPIView.throttle_classes = getattr(func, 'throttle_classes',
|
||||
APIView.throttle_classes)
|
||||
|
||||
WrappedAPIView.permission_classes = getattr(func, 'permission_classes',
|
||||
APIView.permission_classes)
|
||||
|
||||
WrappedAPIView.schema = getattr(func, 'schema',
|
||||
APIView.schema)
|
||||
|
||||
return WrappedAPIView.as_view()
|
||||
|
||||
return decorator
|
||||
|
||||
|
||||
def renderer_classes(renderer_classes):
|
||||
def decorator(func):
|
||||
func.renderer_classes = renderer_classes
|
||||
return func
|
||||
return decorator
|
||||
|
||||
|
||||
def parser_classes(parser_classes):
|
||||
def decorator(func):
|
||||
func.parser_classes = parser_classes
|
||||
return func
|
||||
return decorator
|
||||
|
||||
|
||||
def authentication_classes(authentication_classes):
|
||||
def decorator(func):
|
||||
func.authentication_classes = authentication_classes
|
||||
return func
|
||||
return decorator
|
||||
|
||||
|
||||
def throttle_classes(throttle_classes):
|
||||
def decorator(func):
|
||||
func.throttle_classes = throttle_classes
|
||||
return func
|
||||
return decorator
|
||||
|
||||
|
||||
def permission_classes(permission_classes):
|
||||
def decorator(func):
|
||||
func.permission_classes = permission_classes
|
||||
return func
|
||||
return decorator
|
||||
|
||||
|
||||
def schema(view_inspector):
|
||||
def decorator(func):
|
||||
func.schema = view_inspector
|
||||
return func
|
||||
return decorator
|
||||
|
||||
|
||||
def action(methods=None, detail=None, url_path=None, url_name=None, **kwargs):
|
||||
"""
|
||||
Mark a ViewSet method as a routable action.
|
||||
|
||||
`@action`-decorated functions will be endowed with a `mapping` property,
|
||||
a `MethodMapper` that can be used to add additional method-based behaviors
|
||||
on the routed action.
|
||||
|
||||
:param methods: A list of HTTP method names this action responds to.
|
||||
Defaults to GET only.
|
||||
:param detail: Required. Determines whether this action applies to
|
||||
instance/detail requests or collection/list requests.
|
||||
:param url_path: Define the URL segment for this action. Defaults to the
|
||||
name of the method decorated.
|
||||
:param url_name: Define the internal (`reverse`) URL name for this action.
|
||||
Defaults to the name of the method decorated with underscores
|
||||
replaced with dashes.
|
||||
:param kwargs: Additional properties to set on the view. This can be used
|
||||
to override viewset-level *_classes settings, equivalent to
|
||||
how the `@renderer_classes` etc. decorators work for function-
|
||||
based API views.
|
||||
"""
|
||||
methods = ['get'] if methods is None else methods
|
||||
methods = [method.lower() for method in methods]
|
||||
|
||||
assert detail is not None, (
|
||||
"@action() missing required argument: 'detail'"
|
||||
)
|
||||
|
||||
# name and suffix are mutually exclusive
|
||||
if 'name' in kwargs and 'suffix' in kwargs:
|
||||
raise TypeError("`name` and `suffix` are mutually exclusive arguments.")
|
||||
|
||||
def decorator(func):
|
||||
func.mapping = MethodMapper(func, methods)
|
||||
|
||||
func.detail = detail
|
||||
func.url_path = url_path if url_path else func.__name__
|
||||
func.url_name = url_name if url_name else func.__name__.replace('_', '-')
|
||||
|
||||
# These kwargs will end up being passed to `ViewSet.as_view()` within
|
||||
# the router, which eventually delegates to Django's CBV `View`,
|
||||
# which assigns them as instance attributes for each request.
|
||||
func.kwargs = kwargs
|
||||
|
||||
# Set descriptive arguments for viewsets
|
||||
if 'name' not in kwargs and 'suffix' not in kwargs:
|
||||
func.kwargs['name'] = pretty_name(func.__name__)
|
||||
func.kwargs['description'] = func.__doc__ or None
|
||||
|
||||
return func
|
||||
return decorator
|
||||
|
||||
|
||||
class MethodMapper(dict):
|
||||
"""
|
||||
Enables mapping HTTP methods to different ViewSet methods for a single,
|
||||
logical action.
|
||||
|
||||
Example usage:
|
||||
|
||||
class MyViewSet(ViewSet):
|
||||
|
||||
@action(detail=False)
|
||||
def example(self, request, **kwargs):
|
||||
...
|
||||
|
||||
@example.mapping.post
|
||||
def create_example(self, request, **kwargs):
|
||||
...
|
||||
"""
|
||||
|
||||
def __init__(self, action, methods):
|
||||
self.action = action
|
||||
for method in methods:
|
||||
self[method] = self.action.__name__
|
||||
|
||||
def _map(self, method, func):
|
||||
assert method not in self, (
|
||||
"Method '%s' has already been mapped to '.%s'." % (method, self[method]))
|
||||
assert func.__name__ != self.action.__name__, (
|
||||
"Method mapping does not behave like the property decorator. You "
|
||||
"cannot use the same method name for each mapping declaration.")
|
||||
|
||||
self[method] = func.__name__
|
||||
|
||||
return func
|
||||
|
||||
def get(self, func):
|
||||
return self._map('get', func)
|
||||
|
||||
def post(self, func):
|
||||
return self._map('post', func)
|
||||
|
||||
def put(self, func):
|
||||
return self._map('put', func)
|
||||
|
||||
def patch(self, func):
|
||||
return self._map('patch', func)
|
||||
|
||||
def delete(self, func):
|
||||
return self._map('delete', func)
|
||||
|
||||
def head(self, func):
|
||||
return self._map('head', func)
|
||||
|
||||
def options(self, func):
|
||||
return self._map('options', func)
|
||||
|
||||
def trace(self, func):
|
||||
return self._map('trace', func)
|
||||
88
env/lib/python3.10/site-packages/rest_framework/documentation.py
vendored
Normal file
88
env/lib/python3.10/site-packages/rest_framework/documentation.py
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
from django.urls import include, path
|
||||
|
||||
from rest_framework.renderers import (
|
||||
CoreJSONRenderer, DocumentationRenderer, SchemaJSRenderer
|
||||
)
|
||||
from rest_framework.schemas import SchemaGenerator, get_schema_view
|
||||
from rest_framework.settings import api_settings
|
||||
|
||||
|
||||
def get_docs_view(
|
||||
title=None, description=None, schema_url=None, urlconf=None,
|
||||
public=True, patterns=None, generator_class=SchemaGenerator,
|
||||
authentication_classes=api_settings.DEFAULT_AUTHENTICATION_CLASSES,
|
||||
permission_classes=api_settings.DEFAULT_PERMISSION_CLASSES,
|
||||
renderer_classes=None):
|
||||
|
||||
if renderer_classes is None:
|
||||
renderer_classes = [DocumentationRenderer, CoreJSONRenderer]
|
||||
|
||||
return get_schema_view(
|
||||
title=title,
|
||||
url=schema_url,
|
||||
urlconf=urlconf,
|
||||
description=description,
|
||||
renderer_classes=renderer_classes,
|
||||
public=public,
|
||||
patterns=patterns,
|
||||
generator_class=generator_class,
|
||||
authentication_classes=authentication_classes,
|
||||
permission_classes=permission_classes,
|
||||
)
|
||||
|
||||
|
||||
def get_schemajs_view(
|
||||
title=None, description=None, schema_url=None, urlconf=None,
|
||||
public=True, patterns=None, generator_class=SchemaGenerator,
|
||||
authentication_classes=api_settings.DEFAULT_AUTHENTICATION_CLASSES,
|
||||
permission_classes=api_settings.DEFAULT_PERMISSION_CLASSES):
|
||||
renderer_classes = [SchemaJSRenderer]
|
||||
|
||||
return get_schema_view(
|
||||
title=title,
|
||||
url=schema_url,
|
||||
urlconf=urlconf,
|
||||
description=description,
|
||||
renderer_classes=renderer_classes,
|
||||
public=public,
|
||||
patterns=patterns,
|
||||
generator_class=generator_class,
|
||||
authentication_classes=authentication_classes,
|
||||
permission_classes=permission_classes,
|
||||
)
|
||||
|
||||
|
||||
def include_docs_urls(
|
||||
title=None, description=None, schema_url=None, urlconf=None,
|
||||
public=True, patterns=None, generator_class=SchemaGenerator,
|
||||
authentication_classes=api_settings.DEFAULT_AUTHENTICATION_CLASSES,
|
||||
permission_classes=api_settings.DEFAULT_PERMISSION_CLASSES,
|
||||
renderer_classes=None):
|
||||
docs_view = get_docs_view(
|
||||
title=title,
|
||||
description=description,
|
||||
schema_url=schema_url,
|
||||
urlconf=urlconf,
|
||||
public=public,
|
||||
patterns=patterns,
|
||||
generator_class=generator_class,
|
||||
authentication_classes=authentication_classes,
|
||||
renderer_classes=renderer_classes,
|
||||
permission_classes=permission_classes,
|
||||
)
|
||||
schema_js_view = get_schemajs_view(
|
||||
title=title,
|
||||
description=description,
|
||||
schema_url=schema_url,
|
||||
urlconf=urlconf,
|
||||
public=public,
|
||||
patterns=patterns,
|
||||
generator_class=generator_class,
|
||||
authentication_classes=authentication_classes,
|
||||
permission_classes=permission_classes,
|
||||
)
|
||||
urls = [
|
||||
path('', docs_view, name='docs-index'),
|
||||
path('schema.js', schema_js_view, name='schema-js')
|
||||
]
|
||||
return include((urls, 'api-docs'), namespace='api-docs')
|
||||
264
env/lib/python3.10/site-packages/rest_framework/exceptions.py
vendored
Normal file
264
env/lib/python3.10/site-packages/rest_framework/exceptions.py
vendored
Normal file
@@ -0,0 +1,264 @@
|
||||
"""
|
||||
Handled exceptions raised by REST framework.
|
||||
|
||||
In addition, Django's built in 403 and 404 exceptions are handled.
|
||||
(`django.http.Http404` and `django.core.exceptions.PermissionDenied`)
|
||||
"""
|
||||
import math
|
||||
|
||||
from django.http import JsonResponse
|
||||
from django.utils.encoding import force_str
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.utils.translation import ngettext
|
||||
|
||||
from rest_framework import status
|
||||
from rest_framework.utils.serializer_helpers import ReturnDict, ReturnList
|
||||
|
||||
|
||||
def _get_error_details(data, default_code=None):
|
||||
"""
|
||||
Descend into a nested data structure, forcing any
|
||||
lazy translation strings or strings into `ErrorDetail`.
|
||||
"""
|
||||
if isinstance(data, (list, tuple)):
|
||||
ret = [
|
||||
_get_error_details(item, default_code) for item in data
|
||||
]
|
||||
if isinstance(data, ReturnList):
|
||||
return ReturnList(ret, serializer=data.serializer)
|
||||
return ret
|
||||
elif isinstance(data, dict):
|
||||
ret = {
|
||||
key: _get_error_details(value, default_code)
|
||||
for key, value in data.items()
|
||||
}
|
||||
if isinstance(data, ReturnDict):
|
||||
return ReturnDict(ret, serializer=data.serializer)
|
||||
return ret
|
||||
|
||||
text = force_str(data)
|
||||
code = getattr(data, 'code', default_code)
|
||||
return ErrorDetail(text, code)
|
||||
|
||||
|
||||
def _get_codes(detail):
|
||||
if isinstance(detail, list):
|
||||
return [_get_codes(item) for item in detail]
|
||||
elif isinstance(detail, dict):
|
||||
return {key: _get_codes(value) for key, value in detail.items()}
|
||||
return detail.code
|
||||
|
||||
|
||||
def _get_full_details(detail):
|
||||
if isinstance(detail, list):
|
||||
return [_get_full_details(item) for item in detail]
|
||||
elif isinstance(detail, dict):
|
||||
return {key: _get_full_details(value) for key, value in detail.items()}
|
||||
return {
|
||||
'message': detail,
|
||||
'code': detail.code
|
||||
}
|
||||
|
||||
|
||||
class ErrorDetail(str):
|
||||
"""
|
||||
A string-like object that can additionally have a code.
|
||||
"""
|
||||
code = None
|
||||
|
||||
def __new__(cls, string, code=None):
|
||||
self = super().__new__(cls, string)
|
||||
self.code = code
|
||||
return self
|
||||
|
||||
def __eq__(self, other):
|
||||
result = super().__eq__(other)
|
||||
if result is NotImplemented:
|
||||
return NotImplemented
|
||||
try:
|
||||
return result and self.code == other.code
|
||||
except AttributeError:
|
||||
return result
|
||||
|
||||
def __ne__(self, other):
|
||||
result = self.__eq__(other)
|
||||
if result is NotImplemented:
|
||||
return NotImplemented
|
||||
return not result
|
||||
|
||||
def __repr__(self):
|
||||
return 'ErrorDetail(string=%r, code=%r)' % (
|
||||
str(self),
|
||||
self.code,
|
||||
)
|
||||
|
||||
def __hash__(self):
|
||||
return hash(str(self))
|
||||
|
||||
|
||||
class APIException(Exception):
|
||||
"""
|
||||
Base class for REST framework exceptions.
|
||||
Subclasses should provide `.status_code` and `.default_detail` properties.
|
||||
"""
|
||||
status_code = status.HTTP_500_INTERNAL_SERVER_ERROR
|
||||
default_detail = _('A server error occurred.')
|
||||
default_code = 'error'
|
||||
|
||||
def __init__(self, detail=None, code=None):
|
||||
if detail is None:
|
||||
detail = self.default_detail
|
||||
if code is None:
|
||||
code = self.default_code
|
||||
|
||||
self.detail = _get_error_details(detail, code)
|
||||
|
||||
def __str__(self):
|
||||
return str(self.detail)
|
||||
|
||||
def get_codes(self):
|
||||
"""
|
||||
Return only the code part of the error details.
|
||||
|
||||
Eg. {"name": ["required"]}
|
||||
"""
|
||||
return _get_codes(self.detail)
|
||||
|
||||
def get_full_details(self):
|
||||
"""
|
||||
Return both the message & code parts of the error details.
|
||||
|
||||
Eg. {"name": [{"message": "This field is required.", "code": "required"}]}
|
||||
"""
|
||||
return _get_full_details(self.detail)
|
||||
|
||||
|
||||
# The recommended style for using `ValidationError` is to keep it namespaced
|
||||
# under `serializers`, in order to minimize potential confusion with Django's
|
||||
# built in `ValidationError`. For example:
|
||||
#
|
||||
# from rest_framework import serializers
|
||||
# raise serializers.ValidationError('Value was invalid')
|
||||
|
||||
class ValidationError(APIException):
|
||||
status_code = status.HTTP_400_BAD_REQUEST
|
||||
default_detail = _('Invalid input.')
|
||||
default_code = 'invalid'
|
||||
|
||||
def __init__(self, detail=None, code=None):
|
||||
if detail is None:
|
||||
detail = self.default_detail
|
||||
if code is None:
|
||||
code = self.default_code
|
||||
|
||||
# For validation failures, we may collect many errors together,
|
||||
# so the details should always be coerced to a list if not already.
|
||||
if isinstance(detail, tuple):
|
||||
detail = list(detail)
|
||||
elif not isinstance(detail, dict) and not isinstance(detail, list):
|
||||
detail = [detail]
|
||||
|
||||
self.detail = _get_error_details(detail, code)
|
||||
|
||||
|
||||
class ParseError(APIException):
|
||||
status_code = status.HTTP_400_BAD_REQUEST
|
||||
default_detail = _('Malformed request.')
|
||||
default_code = 'parse_error'
|
||||
|
||||
|
||||
class AuthenticationFailed(APIException):
|
||||
status_code = status.HTTP_401_UNAUTHORIZED
|
||||
default_detail = _('Incorrect authentication credentials.')
|
||||
default_code = 'authentication_failed'
|
||||
|
||||
|
||||
class NotAuthenticated(APIException):
|
||||
status_code = status.HTTP_401_UNAUTHORIZED
|
||||
default_detail = _('Authentication credentials were not provided.')
|
||||
default_code = 'not_authenticated'
|
||||
|
||||
|
||||
class PermissionDenied(APIException):
|
||||
status_code = status.HTTP_403_FORBIDDEN
|
||||
default_detail = _('You do not have permission to perform this action.')
|
||||
default_code = 'permission_denied'
|
||||
|
||||
|
||||
class NotFound(APIException):
|
||||
status_code = status.HTTP_404_NOT_FOUND
|
||||
default_detail = _('Not found.')
|
||||
default_code = 'not_found'
|
||||
|
||||
|
||||
class MethodNotAllowed(APIException):
|
||||
status_code = status.HTTP_405_METHOD_NOT_ALLOWED
|
||||
default_detail = _('Method "{method}" not allowed.')
|
||||
default_code = 'method_not_allowed'
|
||||
|
||||
def __init__(self, method, detail=None, code=None):
|
||||
if detail is None:
|
||||
detail = force_str(self.default_detail).format(method=method)
|
||||
super().__init__(detail, code)
|
||||
|
||||
|
||||
class NotAcceptable(APIException):
|
||||
status_code = status.HTTP_406_NOT_ACCEPTABLE
|
||||
default_detail = _('Could not satisfy the request Accept header.')
|
||||
default_code = 'not_acceptable'
|
||||
|
||||
def __init__(self, detail=None, code=None, available_renderers=None):
|
||||
self.available_renderers = available_renderers
|
||||
super().__init__(detail, code)
|
||||
|
||||
|
||||
class UnsupportedMediaType(APIException):
|
||||
status_code = status.HTTP_415_UNSUPPORTED_MEDIA_TYPE
|
||||
default_detail = _('Unsupported media type "{media_type}" in request.')
|
||||
default_code = 'unsupported_media_type'
|
||||
|
||||
def __init__(self, media_type, detail=None, code=None):
|
||||
if detail is None:
|
||||
detail = force_str(self.default_detail).format(media_type=media_type)
|
||||
super().__init__(detail, code)
|
||||
|
||||
|
||||
class Throttled(APIException):
|
||||
status_code = status.HTTP_429_TOO_MANY_REQUESTS
|
||||
default_detail = _('Request was throttled.')
|
||||
extra_detail_singular = _('Expected available in {wait} second.')
|
||||
extra_detail_plural = _('Expected available in {wait} seconds.')
|
||||
default_code = 'throttled'
|
||||
|
||||
def __init__(self, wait=None, detail=None, code=None):
|
||||
if detail is None:
|
||||
detail = force_str(self.default_detail)
|
||||
if wait is not None:
|
||||
wait = math.ceil(wait)
|
||||
detail = ' '.join((
|
||||
detail,
|
||||
force_str(ngettext(self.extra_detail_singular.format(wait=wait),
|
||||
self.extra_detail_plural.format(wait=wait),
|
||||
wait))))
|
||||
self.wait = wait
|
||||
super().__init__(detail, code)
|
||||
|
||||
|
||||
def server_error(request, *args, **kwargs):
|
||||
"""
|
||||
Generic 500 error handler.
|
||||
"""
|
||||
data = {
|
||||
'error': 'Server Error (500)'
|
||||
}
|
||||
return JsonResponse(data, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
||||
|
||||
|
||||
def bad_request(request, exception, *args, **kwargs):
|
||||
"""
|
||||
Generic 400 error handler.
|
||||
"""
|
||||
data = {
|
||||
'error': 'Bad Request (400)'
|
||||
}
|
||||
return JsonResponse(data, status=status.HTTP_400_BAD_REQUEST)
|
||||
1910
env/lib/python3.10/site-packages/rest_framework/fields.py
vendored
Normal file
1910
env/lib/python3.10/site-packages/rest_framework/fields.py
vendored
Normal file
File diff suppressed because it is too large
Load Diff
379
env/lib/python3.10/site-packages/rest_framework/filters.py
vendored
Normal file
379
env/lib/python3.10/site-packages/rest_framework/filters.py
vendored
Normal file
@@ -0,0 +1,379 @@
|
||||
"""
|
||||
Provides generic filtering backends that can be used to filter the results
|
||||
returned by list views.
|
||||
"""
|
||||
import operator
|
||||
import warnings
|
||||
from functools import reduce
|
||||
|
||||
from django.core.exceptions import FieldDoesNotExist, ImproperlyConfigured
|
||||
from django.db import models
|
||||
from django.db.models.constants import LOOKUP_SEP
|
||||
from django.template import loader
|
||||
from django.utils.encoding import force_str
|
||||
from django.utils.text import smart_split, unescape_string_literal
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from rest_framework import RemovedInDRF317Warning
|
||||
from rest_framework.compat import coreapi, coreschema
|
||||
from rest_framework.fields import CharField
|
||||
from rest_framework.settings import api_settings
|
||||
|
||||
|
||||
def search_smart_split(search_terms):
|
||||
"""Returns sanitized search terms as a list."""
|
||||
split_terms = []
|
||||
for term in smart_split(search_terms):
|
||||
# trim commas to avoid bad matching for quoted phrases
|
||||
term = term.strip(',')
|
||||
if term.startswith(('"', "'")) and term[0] == term[-1]:
|
||||
# quoted phrases are kept together without any other split
|
||||
split_terms.append(unescape_string_literal(term))
|
||||
else:
|
||||
# non-quoted tokens are split by comma, keeping only non-empty ones
|
||||
for sub_term in term.split(','):
|
||||
if sub_term:
|
||||
split_terms.append(sub_term.strip())
|
||||
return split_terms
|
||||
|
||||
|
||||
class BaseFilterBackend:
|
||||
"""
|
||||
A base class from which all filter backend classes should inherit.
|
||||
"""
|
||||
|
||||
def filter_queryset(self, request, queryset, view):
|
||||
"""
|
||||
Return a filtered queryset.
|
||||
"""
|
||||
raise NotImplementedError(".filter_queryset() must be overridden.")
|
||||
|
||||
def get_schema_fields(self, view):
|
||||
assert coreapi is not None, 'coreapi must be installed to use `get_schema_fields()`'
|
||||
if coreapi is not None:
|
||||
warnings.warn('CoreAPI compatibility is deprecated and will be removed in DRF 3.17', RemovedInDRF317Warning)
|
||||
assert coreschema is not None, 'coreschema must be installed to use `get_schema_fields()`'
|
||||
return []
|
||||
|
||||
def get_schema_operation_parameters(self, view):
|
||||
return []
|
||||
|
||||
|
||||
class SearchFilter(BaseFilterBackend):
|
||||
# The URL query parameter used for the search.
|
||||
search_param = api_settings.SEARCH_PARAM
|
||||
template = 'rest_framework/filters/search.html'
|
||||
lookup_prefixes = {
|
||||
'^': 'istartswith',
|
||||
'=': 'iexact',
|
||||
'@': 'search',
|
||||
'$': 'iregex',
|
||||
}
|
||||
search_title = _('Search')
|
||||
search_description = _('A search term.')
|
||||
|
||||
def get_search_fields(self, view, request):
|
||||
"""
|
||||
Search fields are obtained from the view, but the request is always
|
||||
passed to this method. Sub-classes can override this method to
|
||||
dynamically change the search fields based on request content.
|
||||
"""
|
||||
return getattr(view, 'search_fields', None)
|
||||
|
||||
def get_search_terms(self, request):
|
||||
"""
|
||||
Search terms are set by a ?search=... query parameter,
|
||||
and may be whitespace delimited.
|
||||
"""
|
||||
value = request.query_params.get(self.search_param, '')
|
||||
field = CharField(trim_whitespace=False, allow_blank=True)
|
||||
cleaned_value = field.run_validation(value)
|
||||
return search_smart_split(cleaned_value)
|
||||
|
||||
def construct_search(self, field_name, queryset):
|
||||
lookup = self.lookup_prefixes.get(field_name[0])
|
||||
if lookup:
|
||||
field_name = field_name[1:]
|
||||
else:
|
||||
# Use field_name if it includes a lookup.
|
||||
opts = queryset.model._meta
|
||||
lookup_fields = field_name.split(LOOKUP_SEP)
|
||||
# Go through the fields, following all relations.
|
||||
prev_field = None
|
||||
for path_part in lookup_fields:
|
||||
if path_part == "pk":
|
||||
path_part = opts.pk.name
|
||||
try:
|
||||
field = opts.get_field(path_part)
|
||||
except FieldDoesNotExist:
|
||||
# Use valid query lookups.
|
||||
if prev_field and prev_field.get_lookup(path_part):
|
||||
return field_name
|
||||
else:
|
||||
prev_field = field
|
||||
if hasattr(field, "path_infos"):
|
||||
# Update opts to follow the relation.
|
||||
opts = field.path_infos[-1].to_opts
|
||||
# Otherwise, use the field with icontains.
|
||||
lookup = 'icontains'
|
||||
return LOOKUP_SEP.join([field_name, lookup])
|
||||
|
||||
def must_call_distinct(self, queryset, search_fields):
|
||||
"""
|
||||
Return True if 'distinct()' should be used to query the given lookups.
|
||||
"""
|
||||
for search_field in search_fields:
|
||||
opts = queryset.model._meta
|
||||
if search_field[0] in self.lookup_prefixes:
|
||||
search_field = search_field[1:]
|
||||
# Annotated fields do not need to be distinct
|
||||
if isinstance(queryset, models.QuerySet) and search_field in queryset.query.annotations:
|
||||
continue
|
||||
parts = search_field.split(LOOKUP_SEP)
|
||||
for part in parts:
|
||||
field = opts.get_field(part)
|
||||
if hasattr(field, 'get_path_info'):
|
||||
# This field is a relation, update opts to follow the relation
|
||||
path_info = field.get_path_info()
|
||||
opts = path_info[-1].to_opts
|
||||
if any(path.m2m for path in path_info):
|
||||
# This field is a m2m relation so we know we need to call distinct
|
||||
return True
|
||||
else:
|
||||
# This field has a custom __ query transform but is not a relational field.
|
||||
break
|
||||
return False
|
||||
|
||||
def filter_queryset(self, request, queryset, view):
|
||||
search_fields = self.get_search_fields(view, request)
|
||||
search_terms = self.get_search_terms(request)
|
||||
|
||||
if not search_fields or not search_terms:
|
||||
return queryset
|
||||
|
||||
orm_lookups = [
|
||||
self.construct_search(str(search_field), queryset)
|
||||
for search_field in search_fields
|
||||
]
|
||||
|
||||
base = queryset
|
||||
# generator which for each term builds the corresponding search
|
||||
conditions = (
|
||||
reduce(
|
||||
operator.or_,
|
||||
(models.Q(**{orm_lookup: term}) for orm_lookup in orm_lookups)
|
||||
) for term in search_terms
|
||||
)
|
||||
queryset = queryset.filter(reduce(operator.and_, conditions))
|
||||
|
||||
# Remove duplicates from results, if necessary
|
||||
if self.must_call_distinct(queryset, search_fields):
|
||||
# inspired by django.contrib.admin
|
||||
# this is more accurate than .distinct form M2M relationship
|
||||
# also is cross-database
|
||||
queryset = queryset.filter(pk=models.OuterRef('pk'))
|
||||
queryset = base.filter(models.Exists(queryset))
|
||||
return queryset
|
||||
|
||||
def to_html(self, request, queryset, view):
|
||||
if not getattr(view, 'search_fields', None):
|
||||
return ''
|
||||
|
||||
context = {
|
||||
'param': self.search_param,
|
||||
'term': request.query_params.get(self.search_param, ''),
|
||||
}
|
||||
template = loader.get_template(self.template)
|
||||
return template.render(context)
|
||||
|
||||
def get_schema_fields(self, view):
|
||||
assert coreapi is not None, 'coreapi must be installed to use `get_schema_fields()`'
|
||||
if coreapi is not None:
|
||||
warnings.warn('CoreAPI compatibility is deprecated and will be removed in DRF 3.17', RemovedInDRF317Warning)
|
||||
assert coreschema is not None, 'coreschema must be installed to use `get_schema_fields()`'
|
||||
return [
|
||||
coreapi.Field(
|
||||
name=self.search_param,
|
||||
required=False,
|
||||
location='query',
|
||||
schema=coreschema.String(
|
||||
title=force_str(self.search_title),
|
||||
description=force_str(self.search_description)
|
||||
)
|
||||
)
|
||||
]
|
||||
|
||||
def get_schema_operation_parameters(self, view):
|
||||
return [
|
||||
{
|
||||
'name': self.search_param,
|
||||
'required': False,
|
||||
'in': 'query',
|
||||
'description': force_str(self.search_description),
|
||||
'schema': {
|
||||
'type': 'string',
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
class OrderingFilter(BaseFilterBackend):
|
||||
# The URL query parameter used for the ordering.
|
||||
ordering_param = api_settings.ORDERING_PARAM
|
||||
ordering_fields = None
|
||||
ordering_title = _('Ordering')
|
||||
ordering_description = _('Which field to use when ordering the results.')
|
||||
template = 'rest_framework/filters/ordering.html'
|
||||
|
||||
def get_ordering(self, request, queryset, view):
|
||||
"""
|
||||
Ordering is set by a comma delimited ?ordering=... query parameter.
|
||||
|
||||
The `ordering` query parameter can be overridden by setting
|
||||
the `ordering_param` value on the OrderingFilter or by
|
||||
specifying an `ORDERING_PARAM` value in the API settings.
|
||||
"""
|
||||
params = request.query_params.get(self.ordering_param)
|
||||
if params:
|
||||
fields = [param.strip() for param in params.split(',')]
|
||||
ordering = self.remove_invalid_fields(queryset, fields, view, request)
|
||||
if ordering:
|
||||
return ordering
|
||||
|
||||
# No ordering was included, or all the ordering fields were invalid
|
||||
return self.get_default_ordering(view)
|
||||
|
||||
def get_default_ordering(self, view):
|
||||
ordering = getattr(view, 'ordering', None)
|
||||
if isinstance(ordering, str):
|
||||
return (ordering,)
|
||||
return ordering
|
||||
|
||||
def get_default_valid_fields(self, queryset, view, context={}):
|
||||
# If `ordering_fields` is not specified, then we determine a default
|
||||
# based on the serializer class, if one exists on the view.
|
||||
if hasattr(view, 'get_serializer_class'):
|
||||
try:
|
||||
serializer_class = view.get_serializer_class()
|
||||
except AssertionError:
|
||||
# Raised by the default implementation if
|
||||
# no serializer_class was found
|
||||
serializer_class = None
|
||||
else:
|
||||
serializer_class = getattr(view, 'serializer_class', None)
|
||||
|
||||
if serializer_class is None:
|
||||
msg = (
|
||||
"Cannot use %s on a view which does not have either a "
|
||||
"'serializer_class', an overriding 'get_serializer_class' "
|
||||
"or 'ordering_fields' attribute."
|
||||
)
|
||||
raise ImproperlyConfigured(msg % self.__class__.__name__)
|
||||
|
||||
model_class = queryset.model
|
||||
model_property_names = [
|
||||
# 'pk' is a property added in Django's Model class, however it is valid for ordering.
|
||||
attr for attr in dir(model_class) if isinstance(getattr(model_class, attr), property) and attr != 'pk'
|
||||
]
|
||||
|
||||
return [
|
||||
(field.source.replace('.', '__') or field_name, field.label)
|
||||
for field_name, field in serializer_class(context=context).fields.items()
|
||||
if (
|
||||
not getattr(field, 'write_only', False) and
|
||||
not field.source == '*' and
|
||||
field.source not in model_property_names
|
||||
)
|
||||
]
|
||||
|
||||
def get_valid_fields(self, queryset, view, context={}):
|
||||
valid_fields = getattr(view, 'ordering_fields', self.ordering_fields)
|
||||
|
||||
if valid_fields is None:
|
||||
# Default to allowing filtering on serializer fields
|
||||
return self.get_default_valid_fields(queryset, view, context)
|
||||
|
||||
elif valid_fields == '__all__':
|
||||
# View explicitly allows filtering on any model field
|
||||
valid_fields = [
|
||||
(field.name, field.verbose_name) for field in queryset.model._meta.fields
|
||||
]
|
||||
valid_fields += [
|
||||
(key, key.title().split('__'))
|
||||
for key in queryset.query.annotations
|
||||
]
|
||||
else:
|
||||
valid_fields = [
|
||||
(item, item) if isinstance(item, str) else item
|
||||
for item in valid_fields
|
||||
]
|
||||
|
||||
return valid_fields
|
||||
|
||||
def remove_invalid_fields(self, queryset, fields, view, request):
|
||||
valid_fields = [item[0] for item in self.get_valid_fields(queryset, view, {'request': request})]
|
||||
|
||||
def term_valid(term):
|
||||
if term.startswith("-"):
|
||||
term = term[1:]
|
||||
return term in valid_fields
|
||||
|
||||
return [term for term in fields if term_valid(term)]
|
||||
|
||||
def filter_queryset(self, request, queryset, view):
|
||||
ordering = self.get_ordering(request, queryset, view)
|
||||
|
||||
if ordering:
|
||||
return queryset.order_by(*ordering)
|
||||
|
||||
return queryset
|
||||
|
||||
def get_template_context(self, request, queryset, view):
|
||||
current = self.get_ordering(request, queryset, view)
|
||||
current = None if not current else current[0]
|
||||
options = []
|
||||
context = {
|
||||
'request': request,
|
||||
'current': current,
|
||||
'param': self.ordering_param,
|
||||
}
|
||||
for key, label in self.get_valid_fields(queryset, view, context):
|
||||
options.append((key, '%s - %s' % (label, _('ascending'))))
|
||||
options.append(('-' + key, '%s - %s' % (label, _('descending'))))
|
||||
context['options'] = options
|
||||
return context
|
||||
|
||||
def to_html(self, request, queryset, view):
|
||||
template = loader.get_template(self.template)
|
||||
context = self.get_template_context(request, queryset, view)
|
||||
return template.render(context)
|
||||
|
||||
def get_schema_fields(self, view):
|
||||
assert coreapi is not None, 'coreapi must be installed to use `get_schema_fields()`'
|
||||
if coreapi is not None:
|
||||
warnings.warn('CoreAPI compatibility is deprecated and will be removed in DRF 3.17', RemovedInDRF317Warning)
|
||||
assert coreschema is not None, 'coreschema must be installed to use `get_schema_fields()`'
|
||||
return [
|
||||
coreapi.Field(
|
||||
name=self.ordering_param,
|
||||
required=False,
|
||||
location='query',
|
||||
schema=coreschema.String(
|
||||
title=force_str(self.ordering_title),
|
||||
description=force_str(self.ordering_description)
|
||||
)
|
||||
)
|
||||
]
|
||||
|
||||
def get_schema_operation_parameters(self, view):
|
||||
return [
|
||||
{
|
||||
'name': self.ordering_param,
|
||||
'required': False,
|
||||
'in': 'query',
|
||||
'description': force_str(self.ordering_description),
|
||||
'schema': {
|
||||
'type': 'string',
|
||||
},
|
||||
},
|
||||
]
|
||||
295
env/lib/python3.10/site-packages/rest_framework/generics.py
vendored
Normal file
295
env/lib/python3.10/site-packages/rest_framework/generics.py
vendored
Normal file
@@ -0,0 +1,295 @@
|
||||
"""
|
||||
Generic views that provide commonly needed behaviour.
|
||||
"""
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.db.models.query import QuerySet
|
||||
from django.http import Http404
|
||||
from django.shortcuts import get_object_or_404 as _get_object_or_404
|
||||
|
||||
from rest_framework import mixins, views
|
||||
from rest_framework.settings import api_settings
|
||||
|
||||
|
||||
def get_object_or_404(queryset, *filter_args, **filter_kwargs):
|
||||
"""
|
||||
Same as Django's standard shortcut, but make sure to also raise 404
|
||||
if the filter_kwargs don't match the required types.
|
||||
"""
|
||||
try:
|
||||
return _get_object_or_404(queryset, *filter_args, **filter_kwargs)
|
||||
except (TypeError, ValueError, ValidationError):
|
||||
raise Http404
|
||||
|
||||
|
||||
class GenericAPIView(views.APIView):
|
||||
"""
|
||||
Base class for all other generic views.
|
||||
"""
|
||||
# You'll need to either set these attributes,
|
||||
# or override `get_queryset()`/`get_serializer_class()`.
|
||||
# If you are overriding a view method, it is important that you call
|
||||
# `get_queryset()` instead of accessing the `queryset` property directly,
|
||||
# as `queryset` will get evaluated only once, and those results are cached
|
||||
# for all subsequent requests.
|
||||
queryset = None
|
||||
serializer_class = None
|
||||
|
||||
# If you want to use object lookups other than pk, set 'lookup_field'.
|
||||
# For more complex lookup requirements override `get_object()`.
|
||||
lookup_field = 'pk'
|
||||
lookup_url_kwarg = None
|
||||
|
||||
# The filter backend classes to use for queryset filtering
|
||||
filter_backends = api_settings.DEFAULT_FILTER_BACKENDS
|
||||
|
||||
# The style to use for queryset pagination.
|
||||
pagination_class = api_settings.DEFAULT_PAGINATION_CLASS
|
||||
|
||||
# Allow generic typing checking for generic views.
|
||||
def __class_getitem__(cls, *args, **kwargs):
|
||||
return cls
|
||||
|
||||
def get_queryset(self):
|
||||
"""
|
||||
Get the list of items for this view.
|
||||
This must be an iterable, and may be a queryset.
|
||||
Defaults to using `self.queryset`.
|
||||
|
||||
This method should always be used rather than accessing `self.queryset`
|
||||
directly, as `self.queryset` gets evaluated only once, and those results
|
||||
are cached for all subsequent requests.
|
||||
|
||||
You may want to override this if you need to provide different
|
||||
querysets depending on the incoming request.
|
||||
|
||||
(Eg. return a list of items that is specific to the user)
|
||||
"""
|
||||
assert self.queryset is not None, (
|
||||
"'%s' should either include a `queryset` attribute, "
|
||||
"or override the `get_queryset()` method."
|
||||
% self.__class__.__name__
|
||||
)
|
||||
|
||||
queryset = self.queryset
|
||||
if isinstance(queryset, QuerySet):
|
||||
# Ensure queryset is re-evaluated on each request.
|
||||
queryset = queryset.all()
|
||||
return queryset
|
||||
|
||||
def get_object(self):
|
||||
"""
|
||||
Returns the object the view is displaying.
|
||||
|
||||
You may want to override this if you need to provide non-standard
|
||||
queryset lookups. Eg if objects are referenced using multiple
|
||||
keyword arguments in the url conf.
|
||||
"""
|
||||
queryset = self.filter_queryset(self.get_queryset())
|
||||
|
||||
# Perform the lookup filtering.
|
||||
lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field
|
||||
|
||||
assert lookup_url_kwarg in self.kwargs, (
|
||||
'Expected view %s to be called with a URL keyword argument '
|
||||
'named "%s". Fix your URL conf, or set the `.lookup_field` '
|
||||
'attribute on the view correctly.' %
|
||||
(self.__class__.__name__, lookup_url_kwarg)
|
||||
)
|
||||
|
||||
filter_kwargs = {self.lookup_field: self.kwargs[lookup_url_kwarg]}
|
||||
obj = get_object_or_404(queryset, **filter_kwargs)
|
||||
|
||||
# May raise a permission denied
|
||||
self.check_object_permissions(self.request, obj)
|
||||
|
||||
return obj
|
||||
|
||||
def get_serializer(self, *args, **kwargs):
|
||||
"""
|
||||
Return the serializer instance that should be used for validating and
|
||||
deserializing input, and for serializing output.
|
||||
"""
|
||||
serializer_class = self.get_serializer_class()
|
||||
kwargs.setdefault('context', self.get_serializer_context())
|
||||
return serializer_class(*args, **kwargs)
|
||||
|
||||
def get_serializer_class(self):
|
||||
"""
|
||||
Return the class to use for the serializer.
|
||||
Defaults to using `self.serializer_class`.
|
||||
|
||||
You may want to override this if you need to provide different
|
||||
serializations depending on the incoming request.
|
||||
|
||||
(Eg. admins get full serialization, others get basic serialization)
|
||||
"""
|
||||
assert self.serializer_class is not None, (
|
||||
"'%s' should either include a `serializer_class` attribute, "
|
||||
"or override the `get_serializer_class()` method."
|
||||
% self.__class__.__name__
|
||||
)
|
||||
|
||||
return self.serializer_class
|
||||
|
||||
def get_serializer_context(self):
|
||||
"""
|
||||
Extra context provided to the serializer class.
|
||||
"""
|
||||
return {
|
||||
'request': self.request,
|
||||
'format': self.format_kwarg,
|
||||
'view': self
|
||||
}
|
||||
|
||||
def filter_queryset(self, queryset):
|
||||
"""
|
||||
Given a queryset, filter it with whichever filter backend is in use.
|
||||
|
||||
You are unlikely to want to override this method, although you may need
|
||||
to call it either from a list view, or from a custom `get_object`
|
||||
method if you want to apply the configured filtering backend to the
|
||||
default queryset.
|
||||
"""
|
||||
for backend in list(self.filter_backends):
|
||||
queryset = backend().filter_queryset(self.request, queryset, self)
|
||||
return queryset
|
||||
|
||||
@property
|
||||
def paginator(self):
|
||||
"""
|
||||
The paginator instance associated with the view, or `None`.
|
||||
"""
|
||||
if not hasattr(self, '_paginator'):
|
||||
if self.pagination_class is None:
|
||||
self._paginator = None
|
||||
else:
|
||||
self._paginator = self.pagination_class()
|
||||
return self._paginator
|
||||
|
||||
def paginate_queryset(self, queryset):
|
||||
"""
|
||||
Return a single page of results, or `None` if pagination is disabled.
|
||||
"""
|
||||
if self.paginator is None:
|
||||
return None
|
||||
return self.paginator.paginate_queryset(queryset, self.request, view=self)
|
||||
|
||||
def get_paginated_response(self, data):
|
||||
"""
|
||||
Return a paginated style `Response` object for the given output data.
|
||||
"""
|
||||
assert self.paginator is not None
|
||||
return self.paginator.get_paginated_response(data)
|
||||
|
||||
|
||||
# Concrete view classes that provide method handlers
|
||||
# by composing the mixin classes with the base view.
|
||||
|
||||
class CreateAPIView(mixins.CreateModelMixin,
|
||||
GenericAPIView):
|
||||
"""
|
||||
Concrete view for creating a model instance.
|
||||
"""
|
||||
def post(self, request, *args, **kwargs):
|
||||
return self.create(request, *args, **kwargs)
|
||||
|
||||
|
||||
class ListAPIView(mixins.ListModelMixin,
|
||||
GenericAPIView):
|
||||
"""
|
||||
Concrete view for listing a queryset.
|
||||
"""
|
||||
def get(self, request, *args, **kwargs):
|
||||
return self.list(request, *args, **kwargs)
|
||||
|
||||
|
||||
class RetrieveAPIView(mixins.RetrieveModelMixin,
|
||||
GenericAPIView):
|
||||
"""
|
||||
Concrete view for retrieving a model instance.
|
||||
"""
|
||||
def get(self, request, *args, **kwargs):
|
||||
return self.retrieve(request, *args, **kwargs)
|
||||
|
||||
|
||||
class DestroyAPIView(mixins.DestroyModelMixin,
|
||||
GenericAPIView):
|
||||
"""
|
||||
Concrete view for deleting a model instance.
|
||||
"""
|
||||
def delete(self, request, *args, **kwargs):
|
||||
return self.destroy(request, *args, **kwargs)
|
||||
|
||||
|
||||
class UpdateAPIView(mixins.UpdateModelMixin,
|
||||
GenericAPIView):
|
||||
"""
|
||||
Concrete view for updating a model instance.
|
||||
"""
|
||||
def put(self, request, *args, **kwargs):
|
||||
return self.update(request, *args, **kwargs)
|
||||
|
||||
def patch(self, request, *args, **kwargs):
|
||||
return self.partial_update(request, *args, **kwargs)
|
||||
|
||||
|
||||
class ListCreateAPIView(mixins.ListModelMixin,
|
||||
mixins.CreateModelMixin,
|
||||
GenericAPIView):
|
||||
"""
|
||||
Concrete view for listing a queryset or creating a model instance.
|
||||
"""
|
||||
def get(self, request, *args, **kwargs):
|
||||
return self.list(request, *args, **kwargs)
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
return self.create(request, *args, **kwargs)
|
||||
|
||||
|
||||
class RetrieveUpdateAPIView(mixins.RetrieveModelMixin,
|
||||
mixins.UpdateModelMixin,
|
||||
GenericAPIView):
|
||||
"""
|
||||
Concrete view for retrieving, updating a model instance.
|
||||
"""
|
||||
def get(self, request, *args, **kwargs):
|
||||
return self.retrieve(request, *args, **kwargs)
|
||||
|
||||
def put(self, request, *args, **kwargs):
|
||||
return self.update(request, *args, **kwargs)
|
||||
|
||||
def patch(self, request, *args, **kwargs):
|
||||
return self.partial_update(request, *args, **kwargs)
|
||||
|
||||
|
||||
class RetrieveDestroyAPIView(mixins.RetrieveModelMixin,
|
||||
mixins.DestroyModelMixin,
|
||||
GenericAPIView):
|
||||
"""
|
||||
Concrete view for retrieving or deleting a model instance.
|
||||
"""
|
||||
def get(self, request, *args, **kwargs):
|
||||
return self.retrieve(request, *args, **kwargs)
|
||||
|
||||
def delete(self, request, *args, **kwargs):
|
||||
return self.destroy(request, *args, **kwargs)
|
||||
|
||||
|
||||
class RetrieveUpdateDestroyAPIView(mixins.RetrieveModelMixin,
|
||||
mixins.UpdateModelMixin,
|
||||
mixins.DestroyModelMixin,
|
||||
GenericAPIView):
|
||||
"""
|
||||
Concrete view for retrieving, updating or deleting a model instance.
|
||||
"""
|
||||
def get(self, request, *args, **kwargs):
|
||||
return self.retrieve(request, *args, **kwargs)
|
||||
|
||||
def put(self, request, *args, **kwargs):
|
||||
return self.update(request, *args, **kwargs)
|
||||
|
||||
def patch(self, request, *args, **kwargs):
|
||||
return self.partial_update(request, *args, **kwargs)
|
||||
|
||||
def delete(self, request, *args, **kwargs):
|
||||
return self.destroy(request, *args, **kwargs)
|
||||
BIN
env/lib/python3.10/site-packages/rest_framework/locale/ach/LC_MESSAGES/django.mo
vendored
Normal file
BIN
env/lib/python3.10/site-packages/rest_framework/locale/ach/LC_MESSAGES/django.mo
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.10/site-packages/rest_framework/locale/ar/LC_MESSAGES/django.mo
vendored
Normal file
BIN
env/lib/python3.10/site-packages/rest_framework/locale/ar/LC_MESSAGES/django.mo
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.10/site-packages/rest_framework/locale/az/LC_MESSAGES/django.mo
vendored
Normal file
BIN
env/lib/python3.10/site-packages/rest_framework/locale/az/LC_MESSAGES/django.mo
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.10/site-packages/rest_framework/locale/be/LC_MESSAGES/django.mo
vendored
Normal file
BIN
env/lib/python3.10/site-packages/rest_framework/locale/be/LC_MESSAGES/django.mo
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.10/site-packages/rest_framework/locale/bg/LC_MESSAGES/django.mo
vendored
Normal file
BIN
env/lib/python3.10/site-packages/rest_framework/locale/bg/LC_MESSAGES/django.mo
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.10/site-packages/rest_framework/locale/ca/LC_MESSAGES/django.mo
vendored
Normal file
BIN
env/lib/python3.10/site-packages/rest_framework/locale/ca/LC_MESSAGES/django.mo
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.10/site-packages/rest_framework/locale/ca_ES/LC_MESSAGES/django.mo
vendored
Normal file
BIN
env/lib/python3.10/site-packages/rest_framework/locale/ca_ES/LC_MESSAGES/django.mo
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.10/site-packages/rest_framework/locale/cs/LC_MESSAGES/django.mo
vendored
Normal file
BIN
env/lib/python3.10/site-packages/rest_framework/locale/cs/LC_MESSAGES/django.mo
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.10/site-packages/rest_framework/locale/da/LC_MESSAGES/django.mo
vendored
Normal file
BIN
env/lib/python3.10/site-packages/rest_framework/locale/da/LC_MESSAGES/django.mo
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.10/site-packages/rest_framework/locale/de/LC_MESSAGES/django.mo
vendored
Normal file
BIN
env/lib/python3.10/site-packages/rest_framework/locale/de/LC_MESSAGES/django.mo
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.10/site-packages/rest_framework/locale/el/LC_MESSAGES/django.mo
vendored
Normal file
BIN
env/lib/python3.10/site-packages/rest_framework/locale/el/LC_MESSAGES/django.mo
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.10/site-packages/rest_framework/locale/el_GR/LC_MESSAGES/django.mo
vendored
Normal file
BIN
env/lib/python3.10/site-packages/rest_framework/locale/el_GR/LC_MESSAGES/django.mo
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.10/site-packages/rest_framework/locale/en/LC_MESSAGES/django.mo
vendored
Normal file
BIN
env/lib/python3.10/site-packages/rest_framework/locale/en/LC_MESSAGES/django.mo
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.10/site-packages/rest_framework/locale/en_AU/LC_MESSAGES/django.mo
vendored
Normal file
BIN
env/lib/python3.10/site-packages/rest_framework/locale/en_AU/LC_MESSAGES/django.mo
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.10/site-packages/rest_framework/locale/en_CA/LC_MESSAGES/django.mo
vendored
Normal file
BIN
env/lib/python3.10/site-packages/rest_framework/locale/en_CA/LC_MESSAGES/django.mo
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.10/site-packages/rest_framework/locale/en_US/LC_MESSAGES/django.mo
vendored
Normal file
BIN
env/lib/python3.10/site-packages/rest_framework/locale/en_US/LC_MESSAGES/django.mo
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.10/site-packages/rest_framework/locale/es/LC_MESSAGES/django.mo
vendored
Normal file
BIN
env/lib/python3.10/site-packages/rest_framework/locale/es/LC_MESSAGES/django.mo
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.10/site-packages/rest_framework/locale/et/LC_MESSAGES/django.mo
vendored
Normal file
BIN
env/lib/python3.10/site-packages/rest_framework/locale/et/LC_MESSAGES/django.mo
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.10/site-packages/rest_framework/locale/fa/LC_MESSAGES/django.mo
vendored
Normal file
BIN
env/lib/python3.10/site-packages/rest_framework/locale/fa/LC_MESSAGES/django.mo
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.10/site-packages/rest_framework/locale/fa_IR/LC_MESSAGES/django.mo
vendored
Normal file
BIN
env/lib/python3.10/site-packages/rest_framework/locale/fa_IR/LC_MESSAGES/django.mo
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.10/site-packages/rest_framework/locale/fi/LC_MESSAGES/django.mo
vendored
Normal file
BIN
env/lib/python3.10/site-packages/rest_framework/locale/fi/LC_MESSAGES/django.mo
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.10/site-packages/rest_framework/locale/fr/LC_MESSAGES/django.mo
vendored
Normal file
BIN
env/lib/python3.10/site-packages/rest_framework/locale/fr/LC_MESSAGES/django.mo
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.10/site-packages/rest_framework/locale/fr_CA/LC_MESSAGES/django.mo
vendored
Normal file
BIN
env/lib/python3.10/site-packages/rest_framework/locale/fr_CA/LC_MESSAGES/django.mo
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.10/site-packages/rest_framework/locale/gl/LC_MESSAGES/django.mo
vendored
Normal file
BIN
env/lib/python3.10/site-packages/rest_framework/locale/gl/LC_MESSAGES/django.mo
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.10/site-packages/rest_framework/locale/gl_ES/LC_MESSAGES/django.mo
vendored
Normal file
BIN
env/lib/python3.10/site-packages/rest_framework/locale/gl_ES/LC_MESSAGES/django.mo
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.10/site-packages/rest_framework/locale/he_IL/LC_MESSAGES/django.mo
vendored
Normal file
BIN
env/lib/python3.10/site-packages/rest_framework/locale/he_IL/LC_MESSAGES/django.mo
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.10/site-packages/rest_framework/locale/hu/LC_MESSAGES/django.mo
vendored
Normal file
BIN
env/lib/python3.10/site-packages/rest_framework/locale/hu/LC_MESSAGES/django.mo
vendored
Normal file
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user