【问题标题】:DRF - 'str' object has no attribute 'pk'DRF - 'str' 对象没有属性 'pk'
【发布时间】:2018-02-16 11:16:06
【问题描述】:

我有一个前端,它将 JSON 发送到后端以切换数字音频流的输入,并带有一个可选的时间组件来安排未来的切换。以下是完成这项工作的组件:

来自views.py

class SwitchStreamView(views.APIView):
    """
    A custom endpoint for switching inputs of radio streams
    """
    queryset = RadioStream.objects.all()

    def post(self, request, format=None):
        serializer = serializers.RadioSwitchSerializer(data=request.data, many=True)
        serializer.is_valid()
        for stream in serializer.data:
            if stream.schedule_time is None:
                tasks.switch_stream(stream.mnemonic, stream.current_input)
            else:
                tasks.schedule_switch(stream.mnemonic, stream.current_input, stream.schedule_time)
        return HttpResponse('')

来自serializers.py

class RadioSwitchSerializer(serializers.ModelSerializer):
    schedule_time = serializers.SerializerMethodField()

    def get_schedule_time(self, obj):
        return obj.get('schedule_time', None)

    class Meta:
        model = RadioStream
        fields = ('mnemonic', 'current_input', 'schedule_time')

我遇到的问题是,尽管我尝试发送测试 JSON sn-p,但我遇到了错误。使用此设置,发送

[
    {
        "mnemonic": "TEST",
        "current_input": "TEST"
    }
]

导致错误'str' object has no attribute 'pk',但如果我将RadioSwitchSerializer(data=request.data, many=True)更改为many=False,然后发送

{
    "mnemonic": "TEST",
    "current_input": "TEST"
}

我收到了'str' object has no attribute 'schedule_time' 的回复。

我的计划是使用mnemonic 来识别流,并使用current_input 来识别将其切换到哪个输入。我的问题是;为什么这不起作用,我应该为此自定义操作使用非模型序列化程序,而不是尝试将操作适应模型的现有字段?

编辑:这是回溯

Internal Server Error: /api/switch/
Traceback (most recent call last):
  File "...\lib\site-packages\django\core\handlers\exception.py", line 35, in inner
    response = get_response(request)
  File "...\lib\site-packages\django\core\handlers\base.py", line 128, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "...\lib\site-packages\django\core\handlers\base.py", line 126, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "...\lib\site-packages\django\views\decorators\csrf.py", line 54, in wrapped_view
    return view_func(*args, **kwargs)
  File "...\lib\site-packages\django\views\generic\base.py", line 69, in view
    return self.dispatch(request, *args, **kwargs)
  File "...\lib\site-packages\rest_framework\views.py", line 489, in dispatch
    response = self.handle_exception(exc)
  File "...\lib\site-packages\rest_framework\views.py", line 449, in handle_exception
    self.raise_uncaught_exception(exc)
  File "...\lib\site-packages\rest_framework\views.py", line 486, in dispatch
    response = handler(request, *args, **kwargs)
  File "...\radio_switching\views.py", line 45, in post
    for stream in serializer.data:
  File "...\lib\site-packages\rest_framework\serializers.py", line 738, in data
    ret = super(ListSerializer, self).data
  File "...\lib\site-packages\rest_framework\serializers.py", line 266, in data
    self._data = self.get_initial()
  File "...\lib\site-packages\rest_framework\serializers.py", line 573, in get_initial
    return self.to_representation(self.initial_data)
  File "...\lib\site-packages\rest_framework\serializers.py", line 656, in to_representation
    self.child.to_representation(item) for item in iterable
  File "...\lib\site-packages\rest_framework\serializers.py", line 656, in <listcomp>
    self.child.to_representation(item) for item in iterable
  File "...\lib\site-packages\rest_framework\serializers.py", line 500, in to_representation
    ret[field.field_name] = field.to_representation(attribute)
  File "...\lib\site-packages\rest_framework\relations.py", line 259, in to_representation
    return value.pk
AttributeError: 'str' object has no attribute 'pk'

【问题讨论】:

    标签: python django django-rest-framework


    【解决方案1】:

    用这个 sn-p 替换你的 views.py

    class SwitchStreamView(views.APIView):
        """
        A custom endpoint for switching inputs of radio streams
        """
        queryset = RadioStream.objects.all()
    
        def post(self, request, format=None):
            serializer = serializers.RadioSwitchSerializer(data=request.data, many=True)
            serializer.is_valid()
            for stream in serializer.data:
                if 'schedule_time' not in stream:
                    tasks.switch_stream(stream['mnemonic'], stream['current_input'])
                else:
                    tasks.schedule_switch(stream['mnemonic'], stream['current_input'], stream['schedule_time'])
            return HttpResponse('')
    



    错误的原因是,您尝试使用dot operator 访问python dict。要访问字典元素,您可以使用熟悉的方括号以及获取其值的键。这是official doc

    编辑
    AttributeError: 'str' object has no attribute 'pk' 出现此错误,因为您尝试从str 对象访问.pk
    重现错误

    In [7]: my_str = 'this is just a string'
    
    In [8]: my_str.pk
    ---------------------------------------------------------------------------
    AttributeError                            Traceback (most recent call last)
    <ipython-input-8-5bc39c990550> in <module>()
    ----> 1 my_str.pk
    
    AttributeError: 'str' object has no attribute 'pk'
    

    【讨论】:

    • 您可能对这段代码是正确的,但在进行此更改后,我仍然收到'str' object has no attribute 'pk' 错误,所以这不是这里主要错误的原因。也就是说,如果我尝试many=False 版本,我现在得到的是string indices must be integers 而不是'str' object has no attribute 'schedule_time'
    • 在问题部分添加您的回溯
    • 我认为line Number 45 in /radio_switching/views.py 导致了异常。你也可以添加这些相关的行吗?
    • 那行是for stream in serializer.data:,这让我更好地了解现在出了什么问题。我猜serializer.data 不是返回一个数组,而是一个字符串,并且迭代器在迭代它时遇到了麻烦。我会进一步调查。
    【解决方案2】:

    有一些问题,但事实证明,根本问题是 serlializer.data 出于某种原因返回一个字符串而不是一个对象数组。我最终在这里用普通的Serializer 替换了ModelSerializer

    class RadioSwitchSerializer(serializers.Serializer):
        mnemonic = serializers.CharField(max_length=20)
        new_input = serializers.CharField(max_length=20)
        schedule_time = serializers.DateTimeField(allow_null=True)
    

    根据 Jerin 的回答,我还修复了访问 stream 字典的行以使用方括号而不是点运算符。这两件事已经解决了这个问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-07-03
      • 1970-01-01
      • 1970-01-01
      • 2016-04-02
      • 1970-01-01
      • 2021-06-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多