Python / Django Rest Framework只有在使用调试器

时间:2015-05-05 15:42:26

标签: python django django-rest-framework

在更好地查看之后,我自己已经已解决这个问题了。请阅读下面的答案。

我得到的是#34; 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)

在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),则会收到相同的错误,但会指向views.py中的第serializer = serializers.ChHiveLevel1Serializer(hives, fields=fields, many=True)

好吧,我仍然是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')

我知道让3个不同的领域感到困惑。所以我澄清一下:

在观点中,我正在通过一个参数'字段'对于序列化程序,这是一个元组,其中包含要从序列化程序中动态删除的字段名称。然后在 init 内部我弹出这个参数(因此它不会被发送到超类)并为其分配本地元组字段'。最后,在“如果”字段不是“无”字样的内部。我将从self.fields(这些是序列化程序中定义的字段)中删除名称与本地元组内部的字段匹配的字段。我希望我现在可以更好地解释它。

这是一段视频,展示了如何在断点处调试和停止它的工作原理:http://youtu.be/RImEMebBGLY

1 个答案:

答案 0 :(得分:3)

解决方案:首先,在我看来,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,它会起作用。 (如果使用调试器并在断点处停止它突然将('chat')解释为元组而不是字符串)。