Задать вопрос
@tot_samiy_Sergeich

Почему не работает валидация MinValueValidator и MaxValueValidator?

Не работает валидация по количеству (MinValueValidator и MaxValueValidator у поля amount)
Уже всё перепробовал, но на сайте (https://kittygram-puzakov.ru/recipes/create) нет ограничения по количеству и не выводятся сообщения валидации.
Пробовал ограничить по min_value и max_value - не работает
Пробовал отдельно писать валидацию - тоже не работает....
serializers.py
class RecipeIngredientsSerializer(serializers.ModelSerializer):
    id = serializers.PrimaryKeyRelatedField(queryset=Ingredients.objects.all())

    amount = serializers.IntegerField(validators=[MinValueValidator(1, message='Больше 1'), MaxValueValidator(32000, message='Меньше 32000')])

    class Meta:
        model = RecipeIngredients
        fields = "__all__"


class RecipeSerializer(serializers.ModelSerializer):
    ingredients = RecipeIngredientsSerializer(many=True)
    tags = serializers.PrimaryKeyRelatedField(
        many=True, queryset=Tags.objects.all())
    image = Base64ImageField(allow_null=True)
    cooking_time = serializers.IntegerField(
        max_value=MAX_VALUE, min_value=MIN_VALUE)

    class Meta:
        model = Recipe
        fields = "__all__"

    def validate(self, data):
        ingredients = self.initial_data.get("ingredients")
        tags = self.initial_data.get("tags")

        if not ingredients:
            raise serializers.ValidationError(
                'Поле "Ингридиенты" обязательно для заполнения'
            )

        if not tags:
            raise serializers.ValidationError(
                'Поле "Тэги" обязательно для заполнения')

        ingredients_set = set()
        for ingredient in ingredients:
            ingredient_id = ingredient["id"]
            if ingredient_id in ingredients_set:
                raise serializers.ValidationError(
                    "Ингредиенты не должны повторяться")
                
            ingredients_set.add(ingredient_id)

        tags_set = set()
        for tag in tags:
            if tag in tags_set:
                raise serializers.ValidationError("Тэги не должны повторяться")
            tags_set.add(tag)

        return data
    
    def create(self, validated_data):
        ingredients = validated_data.pop("ingredients")
        tags = validated_data.pop("tags")
        recipe = Recipe.objects.create(**validated_data)

        ingredients_list = []
        for one_ingredient in ingredients:
            ingredients_list.append(
                RecipeIngredients(
                    recipe=recipe,
                    ingredient=one_ingredient["id"],
                    amount=one_ingredient["amount"],))
        RecipeIngredients.objects.bulk_create(ingredients_list)

        tags_list = []
        for tag in tags:
            tags_list.append(RecipeTags(tag=tag, recipe=recipe))
        RecipeTags.objects.bulk_create(tags_list)

        return recipe

    def update(self, instance, validated_data):
        instance.image = validated_data.get("image", instance.image)
        instance.name = validated_data.get("name", instance.name)
        instance.text = validated_data.get("text", instance.text)
        instance.cooking_time = validated_data.get(
            "cooking_time", instance.cooking_time
        )

        if "ingredients" in validated_data:
            ingredients_data = validated_data.pop("ingredients")
            RecipeIngredients.objects.filter(recipe=instance).delete()

            ingredients_list = []
            for ingredient in ingredients_data:
                ingredients_list.append(RecipeIngredients(
                    recipe=instance,
                    ingredient=ingredient["id"],
                    amount=ingredient["amount"],))
        RecipeIngredients.objects.bulk_create(ingredients_list)

        if "tags" in validated_data:
            tags_data = validated_data.pop("tags")
            RecipeTags.objects.filter(recipe=instance).delete()
            instance.tags.set(tags_data)
        instance.save()
        return instance

    def to_representation(self, instance):
        representation = RecipeGetSerializer(instance).data
        return representation


models.py
class RecipeIngredients(models.Model):
    recipe = models.ForeignKey(
        Recipe, on_delete=models.CASCADE,
        related_name="recipe_ingredients_recipe_id",
        verbose_name="Id рецепта +")

    ingredient = models.ForeignKey(
        Ingredients, on_delete=models.CASCADE,
        related_name="recipe_ingredients_ingredient_id",
        verbose_name="Id ингридиента +")

    amount = models.PositiveIntegerField(
        "Количество ингридиентов",
        validators=[MinValueValidator(1, message='Больше 1'), MaxValueValidator(32000, message='Меньше 32000')])

    class Meta:
        ordering = ["recipe"]
        verbose_name = "Рецепт/Ингридиент"
        verbose_name_plural = "Рецепты/Ингридиенты"
        constraints = [
            models.UniqueConstraint(
                fields=["recipe", "ingredient"],
                name="unique_recipeingredients",
            )
        ]

    def __str__(self):
        return f"{self.recipe} - {self.ingredient}"

class Recipe(models.Model):
    author = models.ForeignKey(
        User,
        on_delete=models.SET_NULL,
        null=True,
        verbose_name="Автор рецепта",
        related_name="recipe_author"
    )
    ingredients = models.ManyToManyField(
        Ingredients,
        through="RecipeIngredients",
        verbose_name="Ингридиенты рецепта",
    )
    tags = models.ManyToManyField(
        Tags, through="RecipeTags", verbose_name="Тэги рецепта"
    )
    image = models.ImageField(
        upload_to="recipes/images/", verbose_name="Фото рецепта"
    )
    name = models.CharField("Название рецепта", max_length=200)
    text = models.TextField("Описание рецепта")
    cooking_time = models.PositiveIntegerField(
        "Время готовки по рецепту",
        validators=[MinValueValidator(MIN_VALUE),
                    MaxValueValidator(MAX_VALUE)]
    )
    created = models.DateTimeField(
        "Дата и время создания/редактирования рецепта", auto_now_add=True
    )

    class Meta:
        ordering = ["-created"]
        verbose_name = "recipe"
        verbose_name_plural = "recipes"

    def __str__(self):
        return self.name
  • Вопрос задан
  • 88 просмотров
Подписаться 1 Простой 1 комментарий
Пригласить эксперта
Ответы на вопрос 1
@Everything_is_bad
Читай доки, эти валидаторы автоматически работают только в админке и моделформ, для просто модели надо явно вызвать full_clean. И насколько я помню, они не подходят в сериализаторов DRF, там свои, но это не точно, надо проверять, возможно они не работает потому что так реализован create и update.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы