update()引发TypeError:serializer.update()得到了意外的关键字参数“数据”

时间:2019-10-26 22:00:49

标签: python django python-3.x django-rest-framework

一旦数据库已成功发送消息,我就尝试更新它。为此,它将调用序列化程序类的update()方法。这是将更新其实例的模型:

class SMSMessages(models.Model):
    sms_number_to = models.CharField(max_length=14)
    sms_content = models.CharField(max_length=160)
    sending_user = models.ForeignKey("SMSUser", on_delete=models.PROTECT, related_name="user_that_sent")
    sent_date = models.DateTimeField(auto_now=True)
    delivery_status = models.BooleanField(default=False)

    class Meta:
        verbose_name_plural = "SMSMessages"

    def __str__(self):
        return str(self.sending_user)

这是我正在使用的序列化器类:

class SMSMessagesSerializer(serializers.ModelSerializer):
    """
    A class for serializing the SMSMessages model's data. It sub-classes the
    ModelSerializer class from serializer's module.
    """

    class Meta:
        model = SMSMessages
        fields = '__all__'

        def update(self, instance, validated_data):
            """
            This method is used to update an instance of the SMSMessages's delivery_status attribute.
            It get's the value for delivery_status from the input parameter, updates the specific instance
            of the SMSMessagesSerializer, saves that instance and returns it.
            """
            instance = self.get_object()
            instance.delivery_status = validated_data.get('delivery_status', instance.delivery_status)
            instance.save()
            return instance

这是APIView类,具有POST方法,如果消息发送成功,该方法将更新

class SMSView(APIView):
    """
    This class is responsible for all the method operations of an sms. It provides implementations for the GET, POST, and OPTIONS methods.
    Each method provides it's own description.
    """

    serializer_class = SMSMessagesSerializer

    def get(self, request):
        """
        This method is used to GET all created instance of the SMSMessages class that are saved in the db.
        """
        queryset = SMSMessages.objects.filter(sending_user=request.user)
        while queryset:
            return Response(
                data={
                    queryset.values()
                    },
                status=status.HTTP_200_OK,
                content_type="application/json"
            )
        else:
            return Response(
                data={
                    "no sms has been sent"
                },
                status=status.HTTP_404_NOT_FOUND,
                content_type="application/json"
            )

    def post(self, request):
        """
        This method is used to create an instance of the SMSMessages indirectly by using the SMSMessagesSerializer.
        If that is valid it will be passed to the sender() method from the notification.sender module. The serializer
        will be saved, aka the object will be saved to the database, and then the sender() is called. It will run three
        times before it gives up and fails. Once that returns a True value the instance will be called, aka the object
        will be saved to the database, with a delivery_status value of True.
        """
        sms_messages_serializer = SMSMessagesSerializer(
            data={
                "sms_number_to": request.data.get("sms_number_to"),
                "sms_content": request.data.get("sms_content"),
                "sending_user": request.data.get("sending_user")
            }
        )
        permission_classes = (permissions.IsAuthenticated)

        if sms_messages_serializer.is_valid():
            data_to_send = {
                "number": sms_messages_serializer.validated_data[
                    "sms_number_to"
                ],
                "msg_text": sms_messages_serializer.validated_data[
                    "sms_content"
                ]
            }
            sms_messages_serializer.save()

        # TODO refactor this into it's own function
        max_retry = 0
        resp = Response()
        while max_retry < 3:
            max_retry += 1
            status_flag, status_response = sender(data_to_send)
            if not status_flag:
                resp = Response(
                    data={
                        "error": f"{status_response.text}"
                    },
                    status=status_response.status_code,
                    content_type="application/json"
                )
            else:
                sms_messages_serializer.update(
                    data={
                        "delivery_status": True
                    },
                    partial=True
                )
                resp = Response(
                    data={
                        "success": f"{status_response.json()}"
                    },
                    headers=status_response.headers,
                    status=status_response.status_code,
                    content_type="application/json"
                )
                return resp
        else:
            resp = Response(
                data={
                    "error": "unable to send sms"
                },
                status=status.HTTP_500_INTERNAL_SERVER_ERROR,
                content_type="application/json"
            )
            return resp

它将通过以下urlpattern访问:

urlpatterns = [
    path('sendsms/', SMSView.as_view(), name="send_sms"),
    path('viewsms/', SMSView.as_view(), name="view_sms"),
]

但是没有使用python sms_messages_serializer.update(data={"delivery_status": True}partial=True)成功更新实例,而是抛出了 TypeError:serializer.update()得到了意外的关键字参数'data'

我尝试将SMSMessagesSerializer类中的update更改为无效,并尝试将data属性重命名为validated_datavalue,但仍然没有工作。发送短信后,我需要将delivery_status更新为True,该怎么办?

2 个答案:

答案 0 :(得分:1)

对于可能遇到此问题的任何人,我通过将post()方法中的sms_messages_serializer.update()方法更改为以下方法来解决此问题:

 sms_messages_serializer.update(sms_object,{"delivery_status": True})

其中sms_object=sms_object = sms_messages_serializer.save(),表示验证和保存数据后sms_messages_serializer的实例。

不需要data属性或partial=True

答案 1 :(得分:0)

它正在向我显示此错误消息,而就我而言,它没有引起注意。 我将我的解决方案放在这里给其他有相同错误的人: 我在这里放置了模型的名称而不是序列化器的名称:

错误:

class FooViewSet(viewsets.ModelViewSet):
    serializer_class = Foo_model_name

右:

class FooViewSet(viewsets.ModelViewSet):
    serializer_class = Foo_serializer_name