yierstem
yierstem

Reputation: 2067

DRF IntegrityError: NOT NULL constraint failed: user_id

I can't figure out how to pass user object to the following serializer:

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

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

I have this viewset:

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

and this model:

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)

My javascript request looks like this:

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}`
  }
})

It gives me this traceback.

How should I pass the user object to the request?

Thanks in advance.

Upvotes: 1

Views: 1690

Answers (2)

Serghei
Serghei

Reputation: 1

just add this

class ReviewSerializer(serializers.ModelSerializer):
    user = UserSerializer(read_only=True)
    # new line
    user_id = serializers.IntegerField(write_only=True)

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

read_only

Read-only fields are included in the API output, but should not be included in the input during create or update operations. Any 'read_only' fields that are incorrectly included in the serializer input will be ignored.

Set this to True to ensure that the field is used when serializing a representation, but is not used when creating or updating an instance during deserialization.

Defaults to False

write_only

Set this to True to ensure that the field may be used when updating or creating an instance, but is not included when serializing the representation.

Defaults to False

Upvotes: 0

JPG
JPG

Reputation: 88519

Remove read_only=True from serializer

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

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

If you set read_only=True, the DRF will not takes the value from input source even if it's there

From the doc,

Read-only fields are included in the API output, but should not be included in the input during create or update operations. Any 'read_only' fields that are incorrectly included in the serializer input will be ignored.

Set this to True to ensure that the field is used when serializing a representation, but is not used when creating or updating an instance during deserialization.

Defaults to False


UPDATE
You should override the create() method of ReviewSerializer as

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',)



for debug purpose only

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)

Upvotes: 2

Related Questions