인프런 커뮤니티 질문&답변

김영빈님의 프로필 이미지
김영빈

작성한 질문수

파이썬/장고 웹서비스 개발 완벽 가이드 with 리액트

is_valid()과정에서 validated_data에 데이터가 유실됩니다

작성

·

644

0

안녕하세요? 이렇게 빨리 질문을 다시 드릴 줄 몰랐네요 ㅠㅠ
is_valid()과정에서 데이터가 유실되는데, 도무지 이유를 모르겠어서 질문을 드립니다.
 
view 부분은 다음과 같습니다
(편의를 위해data를 그냥 따로 만들었습니다.
def perform_create(self, serializer):
 
data = {
'delivery_location': 'test_location',
'delivery_date': '2022-10-10',
'orderedproducts': [
{'product_id': 3, 'count': 3},
{'product_id': 4, 'count': 3}
],
}
serializer = self.get_serializer(data=data)
 
serializer.is_valid(raise_exception=True)
print(serializer.validated_data)
 
serializer.save()
return serializer.data
 
여기서 print문의 결과로 다음과 같이 출력됩니다.orderedproducts내부에 있어야 할 product_id가 사라져 잇더라구요..아무리 검색해봐도 이유가 나오지 않아서 ㅠㅠ 한번 여쭈어 봅니다.
 
OrderedDict([('delivery_location', 'test_location'), ('delivery_date', datetime.date(2022, 10, 10)), ('orderedproducts', [OrderedDict([('count', 3)]), OrderedDict([('count', 3)])])])
 
혹시 몰라 시리얼라이저와 모델을 같이 적습니다.
 
시리얼라이저는 다음과 같습니다
class OrderedProductSerializer(serializers.ModelSerializer):
product_name = serializers.CharField(source='product.product_name',read_only=True)
 
class Meta:
model = OrderedProduct
fields = [
"product_id","count","product_name"
]
 

class PackageOrderSerializer(serializers.ModelSerializer):
orderedproducts = OrderedProductSerializer(many=True)
 
class Meta:
model = PackageOrder
fields = [
"id","delivery_location","delivery_date","is_packaging",
"orderedproducts"
]
 
def create(self,validated_data):
print("validated_data : ",validated_data)
orderedproducts_data = validated_data.pop('orderedproducts')
packageorder = PackageOrder.objects.create(**validated_data)
 
for products_data in orderedproducts_data:
OrderedProduct.objects.create(package_order=packageorder,**products_data)
 
return packageorder
 
 
모델은 다음과 같습니다
 
#models.py
class OrderedProduct(TimeStampedModel):
package_order = models.ForeignKey('PackageOrder',on_delete=models.CASCADE,related_name='orderedproducts')
product = models.ForeignKey('products.Product',on_delete=models.CASCADE)
count = models.BigIntegerField()
 
class Meta:
db_table = 'ordered_products'

class PackageOrder(TimeStampedModel):
delivery_location = models.CharField(max_length=100)
delivery_date = models.DateField()
is_packaging = models.CharField(max_length=100, blank=True,null=True)
 
class Meta:
db_table = 'package_orders'
 
 
OrderedProduct 모델이 다른 두개의 테이블을 참조하는 중간테이블처럼 사용되는 게 이유가 아닐까..짐작은 해보고 있습니다..
 
정 안되면 body데이터를 pop을 활용해 빼내고 context를 통해 데이터를 전해주는 방식을 사용할까 고민중이긴 한데
 
정확한 이유는 알고 싶어서 질문 드립니다.
 
감사합니다~
 

답변 2

0

김영빈님의 프로필 이미지
김영빈
질문자

찾았네요.. 

nested_serializer에 있는 id field가 read_only로 설정되어 있어서 , 유효성검사 과정에서 해당 필드가 제거돼서 validated_data에서 삭제되나 봅니다.  당연한건데 왜 생각을 못햇나 싶네요 ㅠㅠ

 

다음과 같이 OrderedProductSerializer를 수정해주었습니다

#serializers.py
class OrderedProductSerializer(serializers.ModelSerializer):
product_id = serializers.IntegerField(read_only=False)
product_name = serializers.CharField(source='product.product_name',read_only=True)
 
class Meta:
model = OrderedProduct
fields = [
"product_id","count","product_name"
]

 

질문을 지울까말까 고민하다가, 선생님께서 봐주신 부분도 있고 혹시나 다른분들이 보실 수 있지 않을까 싶어서 삭제하지 않고 질문은 그대로 남겨두겠습니다.

 

참고한 사이트)

https://stackoverflow.com/questions/28247839/django-rest-framework-deserializing-and-get-the-primary-key-from-validated-data

공식 깃헙 issue)

https://github.com/encode/django-rest-framework/issues/2320

이진석님의 프로필 이미지
이진석
지식공유자

잘 찾으셨습니다. 말씀하신 대로 readonly=True 인 속성에 대해서는 DRF에서는 validated_data에서 처음부터 제외시켜버립니다.

이러한 경우 요청 데이터에서 orderedproducts 에 대해서는 OrderedProductSerializer 내에서 custom validate 함수를 구현하셔서 유효성 검사를 수행해보시는 것은 어떨까요?

화이팅입니다. :-)

0

이진석님의 프로필 이미지
이진석
지식공유자

안녕하세요.

PackageOrder 모델 정의는 어떻게 되나요?

 

김영빈님의 프로필 이미지
김영빈
질문자

아 죄송합니다..다른 모델클래스를 올렷네요.
model부분에 수정했습니다!

김영빈님의 프로필 이미지
김영빈

작성한 질문수

질문하기