Это поле обязательно для заполнения 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."
]
}