PolymorphicSerializer
를 사용하고 있을 때 프론트에 주고 받는 데이터의 형태를 같게하기 위해 WritableNestedModelSerializer
를 사용할 때가 왔다.
PolymorphicSerializer
, WritableNestedModelSerializer
를 사용할 때 _save_kwargs
KeyError 가 발생했다. WritableNestedModelSerializer
의 save가 호출되지 않았음을 알았으나 왜 호출되지 않았는지 몰라 하나하나 타고 들어갔다.
from django.db import models
from polymorphic.models import PolymorphicModel
class Component(PolymorphicModel):
class Meta:
verbose_name = "Component"
class ComponentA(Component):
class Meta:
verbose_name = "ComponentA"
subComponent = models.OneToOneField(
"ComponentAA"
on_delete=models.CASCADE
)
class ComponentAA(models.Model):
class Meta:
verbose_name = "Corpus media"
someText = models.Charfield(
default = "some string"
)
from rest_framework import serializers, status, response
from drf_writable_nested import WritableNestedModelSerializer
from rest_polymorphic.serializers import PolymorphicSerializer
from .models import Component, ComponentA, ComponentAA
class ComponentAASerializer(serializer.ModelSerializer):
class Meta:
model = ComponentAA
fields = ('id', 'someText')
class ComponentASerializer(WritableNestedModelSerializer):
subComponent = ComponentAASerializer(many=False)
class Meta:
model = ComponentA
fields = ('id', 'subComponent')
class ComponentSerializer(serializers.ModelSerializer):
class Meta:
model = Component
fields = '__all__'
class ComponentPolymorphicSerializer(PolymorphicSerializer):
class Meta:
model = Component
fields = '__all__'
model_serializer_mapping = {
Component: ComponentSerializer,
ComponentA: ComponentASerializer
}
def to_resource_type(self, model_or_instance):
return model_or_instance._meta.object_name.lower()
class ComponentCreateAPIView(generics.ListCreateAPIView):
queryset = Component.objects.all()
serializer_class = ComponentPolymorphicSerializer
기존에는 위처럼 사용했다. ComponentPolymorphicSerializer
는 PolymorphicSerializer
만 상속받아 resourceType에 따라 Serializer 를 나누어 전달하는 목적이고 나머지는 하위 항목들은 WritableNestedModelSerializer
을 상속받아 하위 모델까지 저장되도록 하고싶었다.
save_kwargs 는 WritableNestedModelSerializer
의 save
에서 채워주게 된다.
하지만 PolymorphicSerializer
와 함께 사용하게되면 WritableNestedModelSerializer
의 save
가 호출되지 않아 ComponentASerializer
를 저장하려 할 때 _save_kwargs
KeyError 가 발생한다.
ComponentCreateAPIView
의 perform_save
에서는 serializer_class
의 save 메서드를 호출한다. 그럼ComponentPolymorphicSerializer
의 save 메서드가 호출된다. Serailizer 기본 save 가 호출 된 후 바로 하위 Serializer(ComponentASerializer
, ComponentAASerializer
)의 create 메서드가 실행된다.
하위 Serializer(ComponentASerializer
, ComponentAASerializer
) 들은 _save_kwargs
를 채워넣지 않은 상태이기 때문에 _get_save_kwrags
메서드를 실행할 때 _save_kwargs 를 사용하려 하면 Error 가 발생한다.
Polymorphic 과 같이 사용하는 Serializer 를 재작성해주었다.
class WritableNestedPolymorphicModelSerializer(WritableNestedModelSerializer):
def _get_save_kwargs(self, field_name):
if hasattr(self, '_save_kwargs'):
save_kwargs = self._save_kwargs.get(field_name, {})
if not isinstance(save_kwargs, dict):
raise TypeError(
_("Arguments to nested serializer's `save` must be dict's")
)
else:
save_kwargs = {}
return save_kwargs