Python/Django Rest Framework只有在使用调试器时才会发生奇怪的错误

die*_*pau 12 python django django-rest-framework

这个问题已经由我自己解决了.请阅读下面的答案.


我得到一个" fields选项必须是列表或元组.得到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)
Run Code Online (Sandbox Code Playgroud)

在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)
    ...
Run Code Online (Sandbox Code Playgroud)

这是追溯:

    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
Run Code Online (Sandbox Code Playgroud)

如果我删除print("fields to be included: ", self.fields)然后我得到相同的错误,但它将指向serializer = serializers.ChHiveLevel1Serializer(hives, fields=fields, many=True)views.py中的行

好吧,我仍然是Python中的菜鸟,我可能会做一些非常错误的事情,但我无法理解的是,如果我在我刚才提到的印刷品中插入一个断点,我会做同样的api请求.调试,然后代码正常工作:我得到了我想要的响应,它没有给出任何错误(如果我删除断点,它将再次给出错误,即使启动与调试器).

你们有什么可能的错误吗?非常感谢提前.如果您需要,请向我询问任何额外信息!

编辑:进一步说明:

整个序列化器是这样的:

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')
Run Code Online (Sandbox Code Playgroud)

我知道它有3个不同的"字段"令人困惑,所以我澄清一下:

在视图中我将一个参数"字段"传递给序列化程序,这是一个包含要从序列化程序中动态删除的字段名称的元组.然后在init中我弹出这个参数(因此它不会被发送到超类)并为它分配本地元组'fields'.最后,在'if fields is not None'中,我将从self.fields(这些是序列化程序中定义的字段)中删除名称与本地元组内部匹配的字段.我希望我现在可以更好地解释它.

这是一个视频,显示在断点处调试和停止时它是如何工作的:http://youtu.be/RImEMebBGLY

die*_*pau 4

解决方案:首先,在我看来,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')
Run Code Online (Sandbox Code Playgroud)

正如错误所述,字段被定义为字符串而不是元组。正确的形式是:

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', )
Run Code Online (Sandbox Code Playgroud)

虽然我同意我在定义这个元组时犯了一个错误,但我仍然无法理解为什么将调试器设置为 ON 时它会正常工作。(就像使用调试器并在断点处停止一样,它突然将(“聊天”)解释为元组而不是字符串)。