Это поле обязательно для заполнения DRF Nested Serializers

Я получаю ошибку This field is required при создании вложенного сериализатора. У меня есть модели ReviewRatings и ReviewImages, в которых ReviewImages является FK к ReviewRatings, чтобы пользователь мог загрузить одно или несколько изображений вместе с отзывами. И проблема возникает, когда я не добавляю required=True в сериализатор. Если это False, то проблемы вообще не возникает.

#Models.py


class ReviewRatings(models.Model):
    user = models.ForeignKey(Account, on_delete=models.CASCADE)
    product = models.ForeignKey(Products, on_delete=models.CASCADE)
    rating = models.FloatField(validators=[MinValueValidator(0), MaxValueValidator(5)])
    created_at = models.DateField(auto_now_add=True)
    review = models.CharField(max_length=500, null=True)
    updated_at = models.DateField(auto_now=True)

    class Meta:
        verbose_name_plural = "Reviews & Ratings"

    def __str__(self):
        return self.product.product_name


class ReviewImages(models.Model):
    review = models.ForeignKey(
        ReviewRatings,
        on_delete=models.CASCADE,
        related_name="review_images",
        null=True,
        blank=True,
    )
    images = models.ImageField(upload_to="reviews/review-images", null=True, blank=True)

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

#Serializers.py


class ReviewImagesSerializer(ModelSerializer):
    class Meta:
        model = ReviewImages
        fields = ["images"]


class ReviewSerializer(ModelSerializer):
    user = SerializerMethodField()
    review_images = ReviewImagesSerializer(many=True, required=False)

    class Meta:
        model = ReviewRatings
        fields = [
            "user",
            "rating",
            "review",
            "created_at",
            "updated_at",
            "review_images",
        ]

    def get_user(self, obj):
        return f"{obj.user.first_name} {obj.user.last_name}"

    def validate(self, obj):
        review_images = self.context["images"]
        max_size = [5 * 1024 * 1024]
        rev_img_size = [i.size for i in review_images]
        if rev_img_size > max_size:
            raise ValidationError({"error": "Size cannot exceed 5 MB"})
        elif len(review_images) > 3:
            raise ValidationError({"error": "you cant upload more than 3 photos"})
        return obj

    def create(self, validated_data):
        review_images = self.context["images"]
        reviews = ReviewRatings.objects.create(**validated_data)
        for image in review_images:
            ReviewImages.objects.create(review=reviews, images=image)
        return reviews

#Views.py

class SubmitReview(APIView):
    permission_classes = [IsAuthenticated]

    def post(self, request, product_slug):
        data = request.data
        review_images = request.FILES.getlist("review_images")
        if data["rating"] == "" and data["review"] == "":
            raise ValidationError({"detail": "Fields cannot be blank"})
        product = Products.objects.get(slug=product_slug)
        if ReviewRatings.objects.filter(
            user=request.user, product__slug=product_slug
        ).exists():
            return Response({"detail": "You have already submitted the review "})
        serializer = ReviewSerializer(
            data=request.data, context={"request": request,'images':review_images}
        )
        if serializer.is_valid():
            serializer.save(user=request.user, product=product)
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        else:
            return Response(serializer.errors)

В этом случае я получаю список изображений (множественная загрузка изображений) и для этого мне нужно сделать review_images = request.FILES.getlist("review_images") и передать его в context в ReviewRatingSerializer.

Итак, если у меня нет required=False в review_images = ReviewImagesSerializer(many=True, required=False) в ReviewRatingSerializer, то создается отзыв вместе с изображениями, в противном случае required=True, то отзыв будет

{
    "review_images": [
        "This field is required."
    ]
}
Вернуться на верх