Python/Django Rest Framework странная ошибка происходит только при использовании отладчика - программирование

Python/Django Rest Framework странная ошибка происходит только при использовании отладчика

Этот вопрос был SOLVED, после того как он лучше посмотрел на него. Пожалуйста, прочтите мой ответ ниже.


Я получаю "Параметр fields должен быть списком или кортежем. Got str." при запуске моего приложения Django. Выполняя точно такой же код с отладчиком, и если у меня есть точка останова в строке ошибки, то это не сработает, и что должно быть кортежем, похоже, является кортежем.

Проблема, похоже, находится в следующем коде внутри DRF ModelSerializer:

def __init__(self, *args, **kwargs):
    # Don't pass the 'fields' arg up to the superclass

    fields = kwargs.pop('fields', None)

    # Instantiate the superclass normally
    super(ChHiveLevel1Serializer, self).__init__(*args, **kwargs)

    if fields is not None:
        # Drop fields that are specified in the `fields` argument.
        for field_name in fields:
            self.fields.pop(field_name)
            print("fields to be included: ", self.fields)

В views.py я просто делаю:       ...

    hives = profile.hive_subscriptions
    # En fields se le pasa el campo a eliminar del serializador
    fields = ('priority', )
    serializer = serializers.ChHiveLevel1Serializer(hives, fields=fields, many=True)
    ...

И это трассировка:

    Internal Server Error: /profiles/diegoocampo8/hives/
    Traceback (most recent call last):
      File "/home/diego/virtualenvs/chattyhive3.3.4/lib/python3.3/site-packages/django/core/handlers/base.py", line 111, in get_response
        response = wrapped_callback(request, *callback_args, **callback_kwargs)
      File "/home/diego/virtualenvs/chattyhive3.3.4/lib/python3.3/site-packages/django/views/decorators/csrf.py", line 57, in wrapped_view
        return view_func(*args, **kwargs)
      File "/home/diego/virtualenvs/chattyhive3.3.4/lib/python3.3/site-packages/django/views/generic/base.py", line 69, in view
        return self.dispatch(request, *args, **kwargs)
      File "/home/diego/virtualenvs/chattyhive3.3.4/lib/python3.3/site-packages/rest_framework/views.py", line 452, in dispatch
        response = self.handle_exception(exc)
      File "/home/diego/virtualenvs/chattyhive3.3.4/lib/python3.3/site-packages/rest_framework/views.py", line 449, in dispatch
        response = handler(request, *args, **kwargs)
      File "/home/diego/PycharmProjects/chattyhive/API/views.py", line 271, in get
        serializer = serializers.ChHiveLevel1Serializer(hives, fields=fields, many=True)
      File "/home/diego/virtualenvs/chattyhive3.3.4/lib/python3.3/site-packages/rest_framework/serializers.py", line 96, in __new__
        return cls.many_init(*args, **kwargs)
      File "/home/diego/virtualenvs/chattyhive3.3.4/lib/python3.3/site-packages/rest_framework/serializers.py", line 116, in many_init
        child_serializer = cls(*args, **kwargs)
      File "/home/diego/PycharmProjects/chattyhive/API/serializers.py", line 274, in __init__
        print("fields to be included: ", self.fields)
      File "/home/diego/virtualenvs/chattyhive3.3.4/lib/python3.3/site-packages/rest_framework/utils/serializer_helpers.py", line 120, in __repr__
        return dict.__repr__(self.fields)
      File "/home/diego/virtualenvs/chattyhive3.3.4/lib/python3.3/site-packages/rest_framework/serializers.py", line 611, in __repr__
        return unicode_to_repr(representation.list_repr(self, indent=1))
      File "/home/diego/virtualenvs/chattyhive3.3.4/lib/python3.3/site-packages/rest_framework/utils/representation.py", line 97, in list_repr
        if hasattr(child, 'fields'):
      File "/home/diego/virtualenvs/chattyhive3.3.4/lib/python3.3/site-packages/rest_framework/serializers.py", line 313, in fields
        for key, value in self.get_fields().items():
      File "/home/diego/virtualenvs/chattyhive3.3.4/lib/python3.3/site-packages/rest_framework/serializers.py", line 837, in get_fields
        field_names = self.get_field_names(declared_fields, info)
      File "/home/diego/virtualenvs/chattyhive3.3.4/lib/python3.3/site-packages/rest_framework/serializers.py", line 889, in get_field_names
        type(fields).__name__
    TypeError: The `fields` option must be a list or tuple. Got str.
    [05/May/2015 17:30:34] "GET /profiles/diegoocampo8/hives/ HTTP/1.1" 500 136024

Если я удалю print("fields to be included: ", self.fields), то я получаю ту же ошибку, но он будет указывать на строку serializer = serializers.ChHiveLevel1Serializer(hives, fields=fields, many=True) в views.py

Хорошо, я все еще ноб в Python, и я мог бы сделать что-то очень не так, но я не могу понять, почему, если я вставляю точку останова в печать, о которой я только что упомянул, и я делаю то же api запрос с отладкой, тогда код просто работает: я получаю свой ответ так, как я хотел, и он не дает никакой ошибки (если я удалю точку останова, он снова даст ошибку, даже если запуск с отладчиком).

Вы, ребята, знаете, что может быть неправильно? Заранее большое спасибо. Спросите меня о дополнительной информации, если вам это нужно.

EDIT: дополнительные пояснения:

Весь сериализатор:

class ChHiveLevel1Serializer(serializers.ModelSerializer):
    """Used by the following API methods: GET hive list,

    """
    category = serializers.SlugRelatedField(read_only=True, slug_field='code')
    languages = serializers.SlugRelatedField(source='_languages', many=True, read_only=True, slug_field='language')

    # If in the POST we only need to establish the relationship with User model (not update the model itself) we
    # set read_only to True
    creator = serializers.SlugRelatedField(read_only=True, slug_field='public_name')
    tags = serializers.SlugRelatedField(many=True, read_only=True, slug_field='tag')
    public_chat = ChPublicChatLevel1Serializer(many=False, read_only=True)
    community_public_chats = ChCommunityPublicChatLevel1Serializer(many=True, read_only=True)

    subscribed_users_count = serializers.IntegerField(source='get_subscribed_users_count', read_only=True)

    def __init__(self, *args, **kwargs):
        # Don't pass the 'fields' arg up to the superclass

        fields = kwargs.pop('fields', None)

        # Instantiate the superclass normally
        super(ChHiveLevel1Serializer, self).__init__(*args, **kwargs)

        if fields is not None:
            # Drop fields that are specified in the `fields` argument.
            for field_name in fields:
                self.fields.pop(field_name)
                print("fields to be included: ", self.fields)

    class Meta:
        model = ChHive
        fields = ('name', 'slug', 'description', 'category', 'languages', 'creator', 'creation_date', 'tags',
                  'priority', 'type', 'public_chat', 'community_public_chats', 'subscribed_users_count')

Я знаю, что сбивает с толку 3 разных поля, поэтому я разъясняю это:

в представлениях я передаю param 'поля' в сериализатор, это кортеж, который содержит имена полей, которые будут динамически удаляться из сериализатора. Затем внутри init я вывожу этот параметр (поэтому он не отправляется в суперкласс) и присваивает ему поля локального кортежа. Наконец, внутри полей "if" не "None" я удаляю из self.fields(это поля, определенные в сериализаторе) поля с именем, соответствующим именам внутри локального кортежа. Надеюсь, теперь я смогу объяснить это лучше.

Вот видео, показывающее, как при отладке и остановке в точке останова это просто работает: http://youtu.be/RImEMebBGLY

4b9b3361

Ответ 1

РЕШЕНИЕ: Прежде всего мне кажется, что есть ошибка с pydevd или Django Rest Framework, что заставило мой код работать в режиме отладки и останавливаться в контрольных точках (показано в видео). Но я не эксперт в Django/Python, поэтому это может быть ожидаемое поведение.

Как видно из приведенного выше кода, сериализатор ChHiveLevel1Serializer имеет вложенные сериализаторы, являющиеся одним из них, например ChPublicChatLevel1Serializer. Посмотрим, как выглядит этот сериализатор:

class ChCommunityPublicChatListLevel1Serializer(serializers.ModelSerializer):
"""Used by the following API methods: GET hive list,

"""
    chat = serializers.SlugRelatedField(read_only=True, slug_field='chat_id', allow_null=True)

    class Meta:
        model = ChCommunityPublicChat
        fields = ('chat')

Как сказано в ошибке, поля определяются как строка вместо кортежа. Правильная форма:

class ChCommunityPublicChatListLevel1Serializer(serializers.ModelSerializer):
"""Used by the following API methods: GET hive list,

"""
    chat = serializers.SlugRelatedField(read_only=True, slug_field='chat_id', allow_null=True)

    class Meta:
        model = ChCommunityPublicChat
        fields = ('chat', )

Пока я согласен с тем, что ошибся в том, как я определил этот кортеж, я все еще не понимаю, почему с отладчиком, установленным в ON, он просто сработает. (например, если использовать отладчик и останавливаться в контрольных точках, он неожиданно интерпретирует ( "чат" ) как кортеж вместо строки).