|
| 1 | +from django import forms |
1 | 2 | from django.contrib import admin |
2 | 3 | from django.contrib.auth import get_user_model |
3 | 4 | from django.contrib.auth.admin import UserAdmin |
| 5 | +from django.core.exceptions import ValidationError |
4 | 6 |
|
| 7 | +from .constants import INGREDIENT_MIN_AMOUNT, MIN_COOKING_TIME |
5 | 8 | from .models import (Favorite, Ingredient, Recipe, RecipeIngredient, |
6 | 9 | ShoppingCart, Tag) |
7 | 10 |
|
8 | 11 | User = get_user_model() |
9 | 12 |
|
10 | 13 |
|
| 14 | +class RecipeAdminForm(forms.ModelForm): |
| 15 | + """Проверка на: |
| 16 | + - минимальное допустимое время приготовления рецепта |
| 17 | + - наличие тегов |
| 18 | + - наличие ингредиентов |
| 19 | + - отсутствие повторяющихся ингредиентов |
| 20 | + - минимальное количество ингредиента |
| 21 | + при добавлении рецепта через админ панель. |
| 22 | + """ |
| 23 | + |
| 24 | + class Meta: |
| 25 | + model = Recipe |
| 26 | + fields = '__all__' |
| 27 | + |
| 28 | + def clean(self): |
| 29 | + cleaned_data = super().clean() |
| 30 | + |
| 31 | + cooking_time = cleaned_data.get("cooking_time") |
| 32 | + if cooking_time and cooking_time < MIN_COOKING_TIME: |
| 33 | + raise ValidationError({ |
| 34 | + 'cooking_time': f'Минимальное время ' |
| 35 | + f'приготовления: {MIN_COOKING_TIME}'}) |
| 36 | + |
| 37 | + tags = cleaned_data.get('tags') |
| 38 | + if not tags or not tags.exists(): |
| 39 | + raise ValidationError( |
| 40 | + {'tags': 'Необходимо указать хотя бы один тег.'}) |
| 41 | + |
| 42 | + instance = self.instance |
| 43 | + if instance.pk: |
| 44 | + if not RecipeIngredient.objects.filter(recipe=instance).exists(): |
| 45 | + raise ValidationError({ |
| 46 | + 'recipe_ingredients': 'Список ' |
| 47 | + 'ингредиентов не может быть ' |
| 48 | + 'пустым.'}) |
| 49 | + |
| 50 | + ingredients_ids_set = set() |
| 51 | + for ri in RecipeIngredient.objects.filter(recipe=instance): |
| 52 | + ingredient_id = ri.ingredient.id |
| 53 | + if ingredient_id in ingredients_ids_set: |
| 54 | + raise ValidationError({ |
| 55 | + 'recipe_ingredients': 'Ингредиенты не должны ' |
| 56 | + 'повторяться.'}) |
| 57 | + if ri.amount < INGREDIENT_MIN_AMOUNT: |
| 58 | + raise ValidationError({ |
| 59 | + 'recipe_ingredients': f'Минимальное количество ' |
| 60 | + f'ингредиента: ' |
| 61 | + f'{INGREDIENT_MIN_AMOUNT}'}) |
| 62 | + ingredients_ids_set.add(ingredient_id) |
| 63 | + |
| 64 | + return cleaned_data |
| 65 | + |
| 66 | + |
11 | 67 | @admin.register(User) |
12 | 68 | class FoodgramUserAdmin(UserAdmin): |
13 | 69 | """Админка для пользователей.""" |
@@ -39,6 +95,7 @@ class RecipeIngredientInline(admin.TabularInline): |
39 | 95 | @admin.register(Recipe) |
40 | 96 | class RecipeAdmin(admin.ModelAdmin): |
41 | 97 | """Админка для рецептов.""" |
| 98 | + form = RecipeAdminForm |
42 | 99 | list_display = ('id', 'name', 'author', |
43 | 100 | 'get_tags', 'favorite_count') |
44 | 101 | search_fields = ('name', 'author__username') |
|
0 commit comments