2023-10-09 03:25:09 -03:00
|
|
|
"""
|
|
|
|
Serializers for recipe APIs
|
|
|
|
"""
|
|
|
|
from rest_framework import serializers
|
|
|
|
|
2023-10-10 00:08:52 -03:00
|
|
|
from core.models import (
|
2023-10-11 01:05:54 -03:00
|
|
|
Ingredient,
|
2023-10-10 00:08:52 -03:00
|
|
|
Recipe,
|
|
|
|
Tag,
|
|
|
|
)
|
2023-10-09 03:25:09 -03:00
|
|
|
|
|
|
|
|
2023-10-11 01:05:54 -03:00
|
|
|
class IngredientSerializer(serializers.ModelSerializer):
|
|
|
|
"""Serializer for Ingredients."""
|
|
|
|
|
|
|
|
class Meta:
|
|
|
|
model = Ingredient
|
|
|
|
fields = ['id', 'name']
|
|
|
|
read_only_fields = ['id']
|
|
|
|
|
|
|
|
|
2023-10-10 14:12:25 -03:00
|
|
|
class TagSerializer(serializers.ModelSerializer):
|
|
|
|
"""Serializer for tags."""
|
|
|
|
|
|
|
|
class Meta:
|
|
|
|
model = Tag
|
|
|
|
fields = ['id', 'name']
|
|
|
|
read_only_fields = ['id']
|
|
|
|
|
|
|
|
|
2023-10-09 03:25:09 -03:00
|
|
|
class RecipeSerializer(serializers.ModelSerializer):
|
|
|
|
"""Serializer for recipes."""
|
2023-10-10 14:12:25 -03:00
|
|
|
tags = TagSerializer(many=True, required=False)
|
2023-10-11 01:05:54 -03:00
|
|
|
ingredients = IngredientSerializer(many=True, required=False)
|
2023-10-09 03:25:09 -03:00
|
|
|
|
|
|
|
class Meta:
|
|
|
|
model = Recipe
|
2023-10-11 01:05:54 -03:00
|
|
|
fields = ['id', 'title', 'time_minutes', 'price', 'link', 'tags',
|
|
|
|
'ingredients']
|
2023-10-09 03:25:09 -03:00
|
|
|
read_only_fields = ['id']
|
2023-10-09 15:34:58 -03:00
|
|
|
|
2023-10-10 14:12:25 -03:00
|
|
|
def _get_or_create_tags(self, tags, recipe):
|
|
|
|
"""Handle getting or creating tags as needed."""
|
|
|
|
auth_user = self.context['request'].user
|
|
|
|
for tag in tags:
|
|
|
|
tag_obj, created = Tag.objects.get_or_create(
|
|
|
|
user=auth_user,
|
|
|
|
**tag,
|
|
|
|
)
|
|
|
|
recipe.tags.add(tag_obj)
|
|
|
|
|
2023-10-11 01:05:54 -03:00
|
|
|
def _get_or_create_ingredients(self, ingredients, recipe):
|
|
|
|
"""Handle getting or creating ingredients as needed."""
|
|
|
|
auth_user = self.context['request'].user
|
|
|
|
for ingredient in ingredients:
|
|
|
|
ingredient_obj, created = Ingredient.objects.get_or_create(
|
|
|
|
user=auth_user,
|
|
|
|
**ingredient,
|
|
|
|
)
|
|
|
|
recipe.ingredients.add(ingredient_obj)
|
|
|
|
|
2023-10-10 14:12:25 -03:00
|
|
|
def create(self, validated_data):
|
|
|
|
"""Create a recipe."""
|
|
|
|
tags = validated_data.pop('tags', [])
|
2023-10-11 01:05:54 -03:00
|
|
|
ingredients = validated_data.pop('ingredients', [])
|
2023-10-10 14:12:25 -03:00
|
|
|
recipe = Recipe.objects.create(**validated_data)
|
|
|
|
self._get_or_create_tags(tags, recipe)
|
2023-10-11 01:05:54 -03:00
|
|
|
self._get_or_create_ingredients(ingredients, recipe)
|
2023-10-10 14:12:25 -03:00
|
|
|
|
|
|
|
return recipe
|
|
|
|
|
|
|
|
def update(self, instance, validated_data):
|
|
|
|
"""Update recipe."""
|
|
|
|
tags = validated_data.pop('tags', None)
|
2023-10-11 01:05:54 -03:00
|
|
|
ingredients = validated_data.pop('ingredients', None)
|
2023-10-10 14:12:25 -03:00
|
|
|
if tags is not None:
|
|
|
|
instance.tags.clear()
|
|
|
|
self._get_or_create_tags(tags, instance)
|
2023-10-11 01:05:54 -03:00
|
|
|
if ingredients is not None:
|
|
|
|
instance.ingredients.clear()
|
|
|
|
self._get_or_create_ingredients(ingredients, instance)
|
2023-10-10 14:12:25 -03:00
|
|
|
|
|
|
|
for attr, value in validated_data.items():
|
|
|
|
setattr(instance, attr, value)
|
|
|
|
|
|
|
|
instance.save()
|
|
|
|
return instance
|
|
|
|
|
2023-10-09 15:34:58 -03:00
|
|
|
|
|
|
|
class RecipeDetailSerializer(RecipeSerializer):
|
|
|
|
"""Serializer for recipe detail view."""
|
|
|
|
|
|
|
|
class Meta(RecipeSerializer.Meta):
|
2023-10-11 17:59:44 -03:00
|
|
|
fields = RecipeSerializer.Meta.fields + ['description', 'image']
|
|
|
|
|
|
|
|
|
|
|
|
class RecipeImageSerializer(serializers.ModelSerializer):
|
|
|
|
"""Serializer for uploading images to recipes."""
|
|
|
|
|
|
|
|
class Meta:
|
|
|
|
model = Recipe
|
|
|
|
fields = ['id', 'image']
|
|
|
|
read_only_fields = ['id']
|
|
|
|
extra_kwargs = {'image': {'required': 'True'}}
|