«объект ‘str’ не вызывается» после того, как я попытался прервать циклический импорт (Django)

#python #django

#python #django

Вопрос:

Я пытался решить эту проблему с циклическим импортом, чтобы реализовать модульное тестирование без сбоев. Если я могу показать вам короткую версию предыдущего решения, которое я получил:

Это….

 serializer_class = serializers.CompanyMappingSerializer
  

должно быть изменено на это:

 serializer_class = "serializers.CompanyMappingSerializer"
  

После этого модульные тесты выполняются нормально. Однако, когда я запускаю api с POSTMAN, он показывает эту ошибку:

 TypeError at /api/v1/company/
'str' object is not callable
  

Что мне делать в этой ситуации?

PS: для получения дополнительной информации здесь приведена полная трассировка:

 Traceback:

File "/Users/nick/myvenv/lib/python3.8/site-packages/django/core/handlers/exception.py" in inner
  34.             response = get_response(request)

File "/Users/nick/myvenv/lib/python3.8/site-packages/django/core/handlers/base.py" in _get_response
  115.                 response = self.process_exception_by_middleware(e, request)

File "/Users/nick/myvenv/lib/python3.8/site-packages/django/core/handlers/base.py" in _get_response
  113.                 response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "/Users/nick/myvenv/lib/python3.8/site-packages/django/views/decorators/csrf.py" in wrapped_view
  54.         return view_func(*args, **kwargs)

File "/Users/nick/myvenv/lib/python3.8/site-packages/rest_framework/viewsets.py" in view
  114.             return self.dispatch(request, *args, **kwargs)

File "/Users/nick/myvenv/lib/python3.8/site-packages/rest_framework/views.py" in dispatch
  505.             response = self.handle_exception(exc)

File "/Users/nick/myvenv/lib/python3.8/site-packages/rest_framework/views.py" in handle_exception
  465.             self.raise_uncaught_exception(exc)

File "/Users/nick/myvenv/lib/python3.8/site-packages/rest_framework/views.py" in raise_uncaught_exception
  476.         raise exc

File "/Users/nick/myvenv/lib/python3.8/site-packages/rest_framework/views.py" in dispatch
  502.             response = handler(request, *args, **kwargs)

File "/Users/nick/work/shiftwork_backend/api/views/company.py" in list
  74.             serializer = self.get_serializer(page, many=True)

File "/Users/nick/myvenv/lib/python3.8/site-packages/rest_framework/generics.py" in get_serializer
  110.         return serializer_class(*args, **kwargs)

Exception Type: TypeError at /api/v1/company/
Exception Value: 'str' object is not callable
  

и ниже приведена более подробная версия api/company.py

 ...
...
from api.models import Company, Pattern, UserCompany, CompanyMapping, Category, COUNTRY_CODE_CHOICES
from statistics.models import CompanySearch
# from api.serializers import CompanySerializer, PatternSerializer, UserCompanySerializer, CompanyMappingSerializer, CategorySerializer
from api import serializers
from api.views import get_user_company_by_local_id, get_user_pattern_by_local_id
...
...
class CompanyMappingViewSet(viewsets.ModelViewSet):
    queryset = CompanyMapping.objects.all()
    serializer_class = serializers.CompanyMappingSerializer
    permission_classes = (IsAuthenticated,)
  

Комментарии:

1. Это означает, что serializer_class — это строка, и я предполагаю, что вы делаете что-то вроде serializer_class() , пожалуйста, включите немного больше кода и полную обратную трассировку ошибок.

2. изменение типа на строку действительно допустимо только для аннотаций типов, а не для фактических типов как переменных первого класса — вам, по всей вероятности, придется прервать фактический цикл

Ответ №1:

Ошибка заключается в том, что вы определили serializer_class атрибут как строку, а не как класс. Таким образом, это должно быть как

 class CompanyMappingViewSet(viewsets.ModelViewSet):
    queryset = CompanyMapping.objects.all()
    serializer_class = serializers.CompanyMappingSerializer
    permission_classes = (IsAuthenticated,)  

Если вы хотите исключить проблему с циклическим импортом, вы можете использовать get_serializer_class(...) метод как,

 class CompanyMappingViewSet(viewsets.ModelViewSet):
    queryset = CompanyMapping.objects.all()
    serializer_class = serializers.CompanyMappingSerializer
    permission_classes = (IsAuthenticated,)

    def get_serializer_class(self):
        from api.serializers import CompanyMappingSerializer
        return CompanyMappingSerializer  

Ответ №2:

Я не знаю, лучшее ли это решение, но если вы не можете что-то сделать, чтобы разорвать циклический цикл, вы можете переопределить свой сериализатор get_serializer_class и добавить свой импорт в этот метод, например:

  class CompanyMappingViewSet(viewsets.ModelViewSet):
    queryset = CompanyMapping.objects.all()
    permission_classes = (IsAuthenticated,)
    
    def get_serializer_class(self):
        from api.serializer import CompanyMappingSerializer
        return CompanyMappingSerializer
  

И это должно предотвратить циклический импорт.