DRF - ' str'对象没有属性' pk'

时间:2018-02-14 23:51:02

标签: python django django-rest-framework

我有一个前端,它将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片段,我都会收到错误。使用此设置,发送

[
    {
        "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'

2 个答案:

答案 0 :(得分:1)

通过此代码段替换您的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('')



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

修改
AttributeError: 'str' object has no attribute 'pk'此错误,因为您尝试从.pk对象访问str的某处 重现错误

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'

答案 1 :(得分:0)

有一些问题,但事实证明根本问题是serlializer.data无论出于何种原因返回字符串而不是对象数组。我最终在此处使用常规ModelSerializer替换了Serializer

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字典的行以使用方括号而不是点运算符。这两件事已经解决了这个问题。