【问题标题】:Django Rest Framework serializer create() doesn't get triggeredDjango Rest Framework 序列化程序 create() 没有被触发
【发布时间】:2019-03-02 13:28:50
【问题描述】:

我有以下序列化程序

class MyModelSerializer(serializers.ModelSerializer):
    user = UserSerializer()

    def create(self, validated_data):
        print("TEST")
        MyModel, created = MyModel.objects.get_or_create(**validated_data)
        return MyModel

    class Meta:
        model = MyModel
        fields = ('pk', 'title', 'user', 'movie', 'timestamp', 'text',)

以及以下视图集:

class MyModelViewSet(viewsets.ModelViewSet):
    queryset = MyModel.objects.all()
    serializer_class = MyModelSerializer

当我向与指定视图集对应的端点发出POST 请求时,create() 方法绝对什么都不做。如您所见,我尝试在控制台TEST 中打印出来,但什么也没有。

有人知道这种奇怪的行为吗?

提前感谢!

编辑: API 调用:

return axios({
  method: 'post',
  url: 'http://localhost:8000/api/mymodel/',
  data: {
     title: this.title,
     movie: this.id,
     text: this.text,
     user: this.user
}

【问题讨论】:

  • 它是否返回任何响应?
  • 不,不管有没有,都是一样的。
  • 确保您发送的数据有效(即响应码为200 / 201)
  • 当我发送数据时,我收到 400 Bad request
  • 如何调用 API?请添加该代码 sn-p 也@yierstem

标签: django django-rest-framework django-serializer


【解决方案1】:

如果您查看 ViewSet 中 POST 处理的实现,您会发现:

def create(self, request, *args, **kwargs):
    serializer = self.get_serializer(data=request.data)
    serializer.is_valid(raise_exception=True)
    self.perform_create(serializer)
    headers = self.get_success_headers(serializer.data)
    return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)

您的create 方法在序列化程序验证数据后被调用。

您看到的错误(用户已存在)是从上面的 sn-p 调用 serializer.is_valid 的结果。

因此,它永远不会调用您的create。您的 create 将作为上述 sn-p 的 self.perform_create() 的一部分调用。

所以这意味着您正在尝试创建一个已经存在的用户。所以在你的模型中你有唯一的用户名。

【讨论】:

  • 我已经通过源代码,我最终得出了相同的结论,但我不知道如何解决它,有没有办法在序列化数据得到验证之前更改它?我应该事先修改 serializer.initial_data 吗?谢谢
  • @yierstem 你为什么要这样做?验证数据是一种很好的做法。无论如何,你必须这样做。序列化程序不会让您在不先调用 is_valid 的情况下调用 save 。如果您不想验证数据而只是调用 create,则根本不要使用序列化程序。
  • 我不想排除数据验证,我想更改传递给序列化程序的数据。出于某种原因,当我只想获取序列化模型的特定实例的用户数据时,它会尝试创建用户记录。我希望它表现得像 Django 中的普通外键,我提交用户 pk,视图从请求中获取用户 pk 以获取必要的用户对象(而不是创建它),创建一个 mymodel 记录,这样我就可以在何时检索它我向 mymodel 视图集发送 get 请求。
  • 那你好像要更新了?所以代替POST,做PUT/PATCH。这将获得一个实例并更新您想要的字段
  • 如果我想为 mymodel 创建新记录而不更改用户的任何内容,我不知道为什么它会是一个放置/补丁,我没有关注。
【解决方案2】:

好的。我找到了一个替代方案。因为我只想要用户对象中的用户名,所以我删除了user = UserSerializer() 并添加了user_username = serializers.ReadOnlyField(source='user.username')

class ReviewSerializer(serializers.ModelSerializer):
    user_username = serializers.ReadOnlyField(source='user.username')

    class Meta:
        model = Review
        fields = ('pk', 'title', 'user', 'user_username', 'movie', 'timestamp', 'review_text',)

user = UserSerializer() 让我头疼,所以我绕过了它。我会检查 Entushiast Martin 的答案作为解决方案,因为他们驱使我找到实际答案。谢谢。

解决了。

【讨论】:

    【解决方案3】:

    这可能是因为您进行了某种错误处理,因为您的 def create 函数的编写方式会引发错误。我测试了下面的代码,它对我有用,试一试:

    class MyModelSerializer(serializers.ModelSerializer):
        user = UserSerializer()
    
        class Meta:
            model = MyModel
            fields = ('pk', 'title', 'user', 'movie', 'timestamp', 'text',)
    
        def create(self, validated_data):
            print("TEST")
            data = validated_data
            data, created = MyModel.objects.get_or_create(**data)
            return data
    

    希望这会有所帮助!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-12-18
      • 2017-06-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-23
      相关资源
      最近更新 更多