반응형
Nested Serializer 란?
DRF에서 제공하는 기능으로, 관계형 데이터를 처리할 때 매우 유용하다. 이 기능을 이용하여 데이터의 중첩된 관계를 표현하고 관리할 수 있다.
Nested Serializer 사용법
코드를 보면 IngredientsSerializer, RecipeProcessSerializer, recipe_comments 세가지 직렬화가 BasicRecipeSerializer에 중첩되어 있는 것을 확인할 수 있다.
like_count와 bookmark_count는 LikeBookmark를 상속받아 중첩시킨 부분이여서 설명에서 제외하였다.
주의 깊게 봐야 되는 부분이 create와 update 메서드 부분인데, nested serializer는 읽기 전용 필드 이기 때문에 따로 create와 update부분을 오버라이드해서 처리해주었다.
class RecipeProcessSerializer(serializers.ModelSerializer):
id = serializers.IntegerField(required=False)
class Meta:
model = RecipeProcess
fields = ["id", "order", "content", "image"]
class IngredientsSerializer(serializers.ModelSerializer):
id = serializers.IntegerField(required=False)
class Meta:
model = Ingredients
fields = ["id", "type", "name", "count", "unit", "etc"]
class BasicRecipeSerializer(serializers.ModelSerializer, LikeBookmark):
user = serializers.StringRelatedField()
recipe_ingredients = IngredientsSerializer(many=True)
recipe_process = RecipeProcessSerializer(many=True)
like_count = serializers.SerializerMethodField(read_only=True)
bookmark_count = serializers.SerializerMethodField(read_only=True)
recipe_comments = CommentSerializer(many=True, read_only=True)
class Meta:
model = FoodRecipes
fields = [
"id",
"categoryCD",
"user",
"title",
"thumnail",
"video",
"intro",
"time",
"people_num",
"difficulty",
"recipe_ingredients",
"recipe_process",
"like_count",
"bookmark_count",
"created_at",
"updated_at",
"recipe_comments",
]
def create(self, validated_data):
ingredients_data = validated_data.pop("recipe_ingredients")
process_datas = validated_data.pop("recipe_process")
user = self.context.get("request").user
if isinstance(user, AnonymousUser):
return print("user not fount")
validated_data["user"] = user
recipe = FoodRecipes.objects.create(**validated_data)
for ingredient_data in ingredients_data:
Ingredients.objects.create(foodrecipe=recipe, **ingredient_data)
for process_data in process_datas:
RecipeProcess.objects.create(foodrecipe=recipe, **process_data)
return recipe
def update(self, instance, validated_data):
ingredients_data = validated_data.pop("recipe_ingredients", "")
process_datas = validated_data.pop("recipe_process", "")
for attr, value in validated_data.items():
setattr(instance, attr, value)
instance.save()
for ingredient_data in ingredients_data:
try:
ingredient = Ingredients.objects.get(pk=ingredient_data["id"])
ingredient.type = ingredient_data.get("type", ingredient.type)
ingredient.name = ingredient_data.get("name", ingredient.name)
ingredient.count = ingredient_data.get("count", ingredient.count)
ingredient.unit = ingredient_data.get("unit", ingredient.unit)
ingredient.etc = ingredient_data.get("etc", ingredient.etc)
ingredient.save()
except Ingredients.DoesNotExist:
Ingredients.objects.create(**ingredient_data)
for process_data in process_datas:
try:
process = RecipeProcess.objects.get(pk=process_data["pk"])
process.order = process.get("order", process.order)
process.image = process.get("image", process.image)
process.content = process.get("content", process.content)
process.save()
except RecipeProcess.DoesNotExist:
RecipeProcess.objects.create(**process_data)
return instance
겪었던 문제점
- 기본적으로 nested serializer는 읽기전용이기 때문에, 모델을 저장, 수정 하려면 create(), update() 메서드를 재정의할 필요가 있다.
- drf-ysag에서 mutipart/form-data와 nested serializer을 동시에 사용하는 것이 불가능하여 postman으로 api 문서화를 진행하였다.
반응형
'BackEnd > Django, DRF' 카테고리의 다른 글
[Django] 장고에서의 페이징 처리 (0) | 2024.08.12 |
---|---|
[Django] 배포 시 에러 로그와 관리자 이메일 발송 (0) | 2024.08.07 |
[Django] admin.ModelAdmin 메서드 정리 (0) | 2024.07.03 |
[Django] Model Meta 설정 Permission을 이용한 사용자 접근 제한 (0) | 2024.07.03 |
[Django] Bulk Operations에 대해서 (0) | 2024.07.03 |