diff --git a/api.http b/api.http index a0cf299..bb4318c 100644 --- a/api.http +++ b/api.http @@ -1,7 +1,13 @@ @baseUrl=http://127.0.0.1:8000/api/v1 ### -GET {{baseUrl}}/recipes HTTP/1.1 +GET {{baseUrl}}/category HTTP/1.1 ### -GET {{baseUrl}}/recipes/76 HTTP/1.1 \ No newline at end of file +GET {{baseUrl}}/program HTTP/1.1 + +### +GET {{baseUrl}}/recipe HTTP/1.1 + +### +GET {{baseUrl}}/recipe/76 HTTP/1.1 \ No newline at end of file diff --git a/api/serializers.py b/api/serializers.py index 1caecbf..9a10b94 100644 --- a/api/serializers.py +++ b/api/serializers.py @@ -3,7 +3,72 @@ from recipes import models -class RecipeSerializer(serializers.ModelSerializer): +class CategorySerializer(serializers.ModelSerializer): + class Meta: + model = models.Category + fields = ("pk", "name") + + +class ProgramSerializer(serializers.ModelSerializer): + class Meta: + model = models.Program + fields = ("pk", "name", "duration") + + +class IngredientSerializer(serializers.ModelSerializer): + class Meta: + model = models.Ingredient + fields = ("pk", "name") + + +class MeasureSerializer(serializers.ModelSerializer): + class Meta: + model = models.Measure + fields = ("short_name", "name") + + +class RecipeIngredientSerializer(serializers.ModelSerializer): + measure = MeasureSerializer() + ingredient = IngredientSerializer() + + class Meta: + model = models.RecipeIngredient + fields = ( + "position", + "ingredient", + "quantity", + "measure", + "volume", + "weight", + "comment", + ) + + +class RecipesListSerializer(serializers.ModelSerializer): + ingredients = serializers.SlugRelatedField( + many=True, read_only=True, slug_field="name" + ) + + class Meta: + model = models.Recipe + fields = ( + "pk", + "name", + "crust", + "description", + "weight", + "thumbnail", + "category", + "program", + "ingredients", + "created_at", + "updated_at", + ) + + +class RecipeDetailsSerializer(serializers.ModelSerializer): + ingredients = RecipeIngredientSerializer(many=True) + class Meta: model = models.Recipe fields = ( @@ -15,6 +80,7 @@ class Meta: "thumbnail", "category", "program", + "ingredients", "created_at", "updated_at", ) diff --git a/api/urls.py b/api/urls.py index a2b3583..e7d6eba 100644 --- a/api/urls.py +++ b/api/urls.py @@ -1,10 +1,16 @@ -from django.urls import path +from django.urls import include, path from rest_framework import routers from api import views router = routers.SimpleRouter(trailing_slash=False) -router.register("recipes", views.RecipesViewSet) +# router.register("recipe", views.RecipesViewSet) +router.register("category", views.CategoriesViewSet) +router.register("program", views.ProgramsViewSet) -urlpatterns = router.urls +urlpatterns = [ + path("", include(router.urls)), + path("recipe/", views.RecipesListView.as_view(), name="recipe-list"), + path("recipe/", views.RecipeDetailsView.as_view(), name="recipe-detail"), +] diff --git a/api/views.py b/api/views.py index 2cecfad..00d48d2 100644 --- a/api/views.py +++ b/api/views.py @@ -5,6 +5,21 @@ # Create your views here. -class RecipesViewSet(viewsets.ReadOnlyModelViewSet): +class CategoriesViewSet(viewsets.ReadOnlyModelViewSet): + queryset = repositories.CategoriesRepository.select() + serializer_class = serializers.CategorySerializer + + +class ProgramsViewSet(viewsets.ReadOnlyModelViewSet): + queryset = repositories.ProgramsRepository.select() + serializer_class = serializers.ProgramSerializer + + +class RecipesListView(generics.ListAPIView): queryset = repositories.RecipesRepository.select() - serializer_class = serializers.RecipeSerializer + serializer_class = serializers.RecipesListSerializer + + +class RecipeDetailsView(generics.RetrieveAPIView): + queryset = repositories.RecipesRepository.get() + serializer_class = serializers.RecipeDetailsSerializer diff --git a/recipes/models.py b/recipes/models.py index e5c9b8d..25d4d28 100644 --- a/recipes/models.py +++ b/recipes/models.py @@ -208,6 +208,10 @@ class RecipeIngredient(models.Model): measure = models.ForeignKey(Measure, on_delete=models.RESTRICT, verbose_name="ЕИ") comment = models.CharField("комментарий", max_length=64, blank=True) + @property + def name(self): + return self.ingredient.name + def volume(self): if self.measure.volume is None: return None diff --git a/recipes/repositories.py b/recipes/repositories.py index 22f1c58..239bd85 100644 --- a/recipes/repositories.py +++ b/recipes/repositories.py @@ -1,3 +1,4 @@ +import abc import random import typing @@ -6,10 +7,35 @@ import recipes.models as models -class RecipesRepository: +class BaseRepository(abc.ABC): + model: djmodels.base.ModelBase + + @classmethod + def select(cls): + return cls.model.objects.all() # type: ignore + + +class CategoriesRepository(BaseRepository): + model = models.Category + + +class ProgramsRepository(BaseRepository): + model = models.Program + + +class RecipesRepository(BaseRepository): + model = models.Recipe + @classmethod def select(cls): - return models.Recipe.objects.all() + return super().select().prefetch_related("ingredients__ingredient").all() + + @classmethod + def get(cls): + return models.Recipe.objects.prefetch_related( + "ingredients__ingredient__measureweight_set__measure", + "ingredients__measure", + ).all() @classmethod def get_random(cls) -> typing.Union[models.Recipe, None]: