【问题标题】:DRF IntegrityError: NOT NULL constraint failed: user_idDRF IntegrityError:NOT NULL 约束失败:user_id
【发布时间】:2019-03-02 06:21:22
【问题描述】:

我不知道如何将用户对象传递给以下序列化程序:

class ReviewSerializer(serializers.ModelSerializer):
    user = UserSerializer(read_only=True)

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

我有这个视图集:

class ReviewsViewSet(viewsets.ModelViewSet):
    queryset = Review.objects.all()
    serializer_class = ReviewSerializer

还有这个模型:

class Review(models.Model):
    title = models.CharField(max_length=255)
    user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='reviews')
    movie = models.ForeignKey(Movie, on_delete=models.CASCADE, related_name='reviews')
    review_text = models.TextField()
    timestamp = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return '{movie} review by {user}'.format(user=self.user, movie=self.movie)

我的 javascript 请求如下所示:

return axios({
  method: 'post',
  url: 'http://localhost:8000/api/reviews/',
  data: { // Using data from Vue
    title: this.review_title,
    movie: this.id,
    review_text: this.review_text,
    user: JSON.stringify(this.user)
  },
  headers: {
    'Content-Type': 'application/json',
    Authorization: `JWT ${token}`
  }
})

它给了我this traceback

我应该如何将用户对象传递给请求?

提前致谢。

【问题讨论】:

    标签: django rest django-models django-rest-framework django-database


    【解决方案1】:

    从序列化程序中删除 read_only=True

    class ReviewSerializer(serializers.ModelSerializer):
        user = UserSerializer()
    
        class Meta:
            model = Review
            fields = ('pk', 'title', 'user', 'movie', 'timestamp', 'review_text',)
    
    

    如果您设置 read_only=True,DRF 不会从输入源获取值,即使它在那里

    From the doc,

    API 输出中包含只读字段,但不应包含 在创建或更新操作期间包含在输入中。任何 序列化程序中错误包含的“read_only”字段 输入将被忽略。

    将此设置为 True 以确保在序列化一个 表示,但在创建或更新实例时不使用 在反序列化期间。

    默认为 False


    更新
    您应该将 ReviewSerializercreate() 方法覆盖为

    class ReviewSerializer(serializers.ModelSerializer):
        user = UserSerializer()
    
        def create(self, validated_data):
            user_dict = validated_data.pop('user')
            user_obj, created = User.objects.get_or_create(**user_dict)
            return Review.objects.create(user=user_obj, **validated_data)
    
        class Meta:
            model = Review
            fields = ('pk', 'title', 'user', 'movie', 'timestamp', 'review_text',)



    仅用于调试目的

    class ReviewsViewSet(viewsets.ModelViewSet):
        queryset = Review.objects.all()
        serializer_class = ReviewSerializer
    
        def create(self, request, *args, **kwargs):
            print(request.data)  # print here <<<<
            return super(ReviewsViewSet, self).create(request, *args, **kwargs)
    

    【讨论】:

    • 是的,但是如果我取出 read_only=True,它会给我:"A user with that username already exists."。所以,我不想发布新用户,只是为了获取创建特定评论所需的用户数据。
    • 您可以添加您从前端传递的user 的值吗?
    • @yierstem 无论如何我已经更新了答案。希望对你有帮助
    • 我传递了存储在 Vuex 中的整个用户对象,以便显示用户详细信息和内容。所以它看起来像这样"{"pk":1,"username":"test","first_name":"test","last_name":"test","email":"test@gmail.com"}"。我发送了一个包含所有必需字段的请求,尤其是用户字段,并返回另一个错误:"user": [ "This field is required." ]
    • 哦,好的,现在可以使用了。感谢您的详细回答,我现在学会了如何调试 DRF。
    猜你喜欢
    • 1970-01-01
    • 2016-09-09
    • 2019-07-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-31
    • 2021-12-17
    • 2021-06-12
    相关资源
    最近更新 更多