【问题标题】:KeyError: 'user_id' when using PUT requestKeyError: 'user_id' 使用 PUT 请求时
【发布时间】:2021-11-22 08:57:57
【问题描述】:

最近开始使用 Django REST 框架。我有一个用户表和另一个表,用于存储每个用户的一些相关数据。我已经很好地设置了 POST/GET/DELETE 方法,但是我无法让 perform_update 工作的方法 - 我在 /api/sdgdata/1 处不断收到 KeyError 当我尝试对用户发出 put 请求时,Postman 中出现“user_id”错误。请看下面的代码:

型号:

class TestDataTwo(models.Model):
    user = models.ForeignKey("auth.User", related_name="testdatatwo", on_delete=models.CASCADE)
    test_name = models.CharField(max_length=1024, null=True, default="N/A")

序列化器:

class TestDataTwoSerializer(serializers.ModelSerializer):

    class Meta:
        model = TestDataTwo
        fields = (
            "id",
            "test_name",
        )

    def update(self, instance, validated_data):

        # get user id from validated data:
        user_id = validated_data.pop('user_id')

        # get user:
        user = User.objects.get(id=user_id)

        # set user on instance:
        instance.user = user
        instance.save()

        # continue with update method:
        super().update(instance, validated_data)

观看次数:

class TestDataTwoViewSet(ModelViewSet):
    queryset = TestDataTwo.objects.all().order_by('id')
    serializer_class = TestDataTwoSerializer
    paginator = None

    # CREATE NEW TESTDATATWO ROW FOR USER
    def perform_create(self, serializer):
        serializer.save(user=self.request.user)

    # GET ALL ENTRIES OF TESTDATATWO FOR SPECIFIC USER, EXCEPT IF SUPERUSER, THEN RETURN ALL
    def get_queryset(self):
        # if self.request.user.is_superuser:
        #     return self.queryset
        # else:
        return self.queryset.filter(user=self.request.user)

    def perform_update(self, serializer):
        instance = self.get_object()
        serializer.save(user=self.request.user)
        return Response(serializer.data, status=status.HTTP_200_OK)

    # DELETE TESTDATATWO ID
    def destroy(self, request, *args, **kwargs):
        instance = self.get_object()
        self.perform_destroy(instance)
        return Response(status=status.HTTP_204_NO_CONTENT)

邮递员 GET:

邮递员 PUT:

我在 perform_update 方法上尝试了许多变体,但我猜我以某种方式缺少对用户 user_id 的引用...感谢任何帮助。

【问题讨论】:

  • 这是因为序列化程序在Meta 中没有基于fields 的字段user_id
  • 嗨@BrianD,我将user_id 字段添加到序列化程序中,但关键错误问题仍然存在。我是否在视图中的 perform_update 方法中遗漏了一些东西? 更新的序列化程序: 类 Meta:model = TestDataTwo fields = ( "id", "user_id", "test_name", )
  • 根据您的代码,您希望用户基于request.user 对吗?在这种情况下,由于您已经在 serializer.save 中将其传递到 perform_update 中,因此您不必处理它。我会试着写一个答案

标签: django postgresql django-rest-framework postman


【解决方案1】:

此错误是由validated_data.pop('user_id') 引起的,因为user_id 没有定义为序列化程序上的字段,也没有在请求数据中传递。看来您的目标是将当前用户保存为正在更新的 TestDataTwo 实例的用户字段。

在这种情况下,您不需要覆盖update,因为在TestDataTwo 实例上基于self.request.user 保存用户已经由序列化程序的save 完成:

def perform_update(self, serializer):
    serializer.save(user=self.request.user)

这意味着你不必再在序列化器中做任何处理,所以它可以只是:

class TestDataTwoSerializer(serializers.ModelSerializer):
    class Meta:
        model = TestDataTwo
        fields = ("id", "test_name",)

    # No need to override update for saving self.request.user to `TestDataTwo`'s user

有关此功能的更多信息,您可以阅读here..[DRF-docs-Passing-additional-attributes-to-save]

【讨论】:

  • 明白了。删除了覆盖的方法并修复了它,非常感谢。
猜你喜欢
  • 2019-05-24
  • 1970-01-01
  • 1970-01-01
  • 2021-04-28
  • 2014-01-15
  • 2019-12-08
  • 2012-07-07
  • 2011-07-29
  • 2013-09-10
相关资源
最近更新 更多