Невозможно поднять APIException из Django ViewSet

У меня есть метод в ViewSet, где я хочу проверить, что request.data является списком. Если это не так, я хотел бы выдать ошибку ParseError().

<
# views.py
class MyViewSet(viewsets.GenericViewSet):
    ...

    @action(methods=['post'], detail=False, url_path='bulk-create')
    def bulk_create(self, request, *args, **kwargs):
        # Assert that request.data is a list of objects
        if not isinstance(request.data, list):
            raise ParseError("Expected the data to be in list format.")

        # Actually process incoming data
        ...
Однако, мой код падает, когда я действительно поднимаю сказанное , и я не понимаю почему. Это подкласс , который, согласно документации , должен обрабатываться автоматически.

Вызов маршрута с помощью чего-либо, кроме списка, правильно вызывает мое утверждение if, но вместо того, чтобы вернуть правильный ответ status.HTTP_400_BAD_REQUEST, сервер падает, и я получаю следующую ошибку:

Traceback (most recent call last):
2022-05-17T12:23:45.366216553Z   File "/opt/venv/lib/python3.9/site-packages/django/core/handlers/exception.py", line 47, in inner
2022-05-17T12:23:45.366221178Z     response = get_response(request)
2022-05-17T12:23:45.366223345Z   File "/opt/venv/lib/python3.9/site-packages/debug_toolbar/middleware.py", line 67, in __call__
2022-05-17T12:23:45.366225470Z     panel.generate_stats(request, response)
2022-05-17T12:23:45.366238220Z   File "/opt/venv/lib/python3.9/site-packages/debug_toolbar/panels/request.py", line 30, in generate_stats
2022-05-17T12:23:45.366240470Z     "post": get_sorted_request_variable(request.POST),
2022-05-17T12:23:45.366346803Z   File "/opt/venv/lib/python3.9/site-packages/debug_toolbar/utils.py", line 227, in get_sorted_request_variable
2022-05-17T12:23:45.366352511Z     return [(k, variable.getlist(k)) for k in sorted(variable)]
2022-05-17T12:23:45.366354803Z TypeError: '<' not supported between instances of 'dict' and 'dict'

Из-за журнала ошибок я подозреваю, что django-debug-toolbar имеет какое-то отношение к моей проблеме. Я уже пробовал перемещать его во все позиции в конфигурации промежуточного ПО, но это не решило мою проблему.

# settings.py
MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'corsheaders.middleware.CorsMiddleware',
    'debug_toolbar.middleware.DebugToolbarMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django_currentuser.middleware.ThreadLocalUserMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'rollbar.contrib.django.middleware.RollbarNotifierMiddleware',
]

Благодаря замечательным людям из django-debug-toolbar, библиотека теперь может работать с массивами верхнего уровня и в POST.data. https://github.com/jazzband/django-debug-toolbar/pull/1624

К сожалению, я столкнулся с той же проблемой в системе тестирования Django...

# test_with_error.py

from rest_framework.test import APITestCase

class DonationBulkCreateRouteTestCase(APITestCase):
    def test_route_permissions(self):
        self.client.post(
            path="/bulk-create/",
            data=json.dumps([], default=json_serializer)
        )

# log.txt

File "/opt/venv/lib/python3.9/site-packages/django/test/client.py", line 245, in encode_multipart
    for (key, value) in data.items():
AttributeError: 'str' object has no attribute 'items'

Итак, хотя массивы верхнего уровня являются допустимым JSON, я решил обернуть свои данные в дополнительный объект, в который я передаю список. Это имеет дополнительное преимущество в том, что его легче расширять в будущем, потому что я могу свободно добавлять ключи, не ломая существующий код.

Вернуться на верх