serializer = serializer_class(data = request.data)
serializer.initial_data['필드'] = 값 or 필드 값을 이용할 수 있음
serializer = serializer_class(data = request.data)
if serializer.is_valid():
serializer.validated_data['필드'] = 값
serializer.save()
serializer = serializer_class(data=request.data)
if serializer.is_valid():
serializer.save()
serializer.data['필드']
class Goods(models.Model):
class Meta:
db_table = 'Goods'
seller = models.ForeignKey(User, on_delete=models.CASCADE, related_name='sell_goods')
title = models.CharField(max_length=256)
content = models.TextField()
class GoodsImage(models.Model):
goods = models.ForeignKey(Goods, on_delete=models.CASCADE)
image = models.ImageField(upload_to='goods/')
예시로 상품 모델이 있고 상품 이미지 모델을 만들었다.
상품에는 여러개의 이미지를 포함시키기 위해 상품이미지 모델을 분리 시켜서 상품을 참조하도록 하였다.
class GoodsImageSerializer(serializers.ModelSerializer):
class Meta:
model = GoodsImage
fields = ['image',]
class GoodsDetailSerializer(serializers.ModelSerializer):
seller = serializers.SerializerMethodField()
goodsimage_set = GoodsImageSerializer(many=True, read_only = True)
# images = serializers.SerializerMethodField()
# def get_images(self, obj):
# return GoodsImageSerializer(obj.goodsimage_set.all(), many = True).data
def get_seller(self, obj):
return obj.seller.username
class Meta:
model = Goods
fields = '__all__'
상품 이미지 모델에서 상품을 참조하기 때문에 상품에서 역참조 시 related_name이 설정되어 있지 않다면 모델_set 필드로 사용하면 되고, 상품 이미지 시리얼 라이저를 통하여 many=True, read_only=True값을 주어서 이미지의 주소 값을 가져올 수 있다.
(주석처럼 SerializerMethodField를 사용해 주어도 된다.)
class GoodsView(ModelViewSet):
queryset = Goods.objects.prefetch_related('goodsimage_set').select_related('seller').all()
serializer_class = GoodsDetailSerializer
permission_classes = [IsAuthorOrReadOnly,]
def get_permissions(self):
if self.action == 'create':
return [permissions.IsAuthenticated(),]
return super(GoodsView, self).get_permissions()
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
images = serializer.initial_data.pop('goodsimage_set') [1]
images = [{'image' : image} for image in images] [2]
serializer.is_valid(raise_exception=True)
obj = self.perform_create(serializer) [3]
image_serializer = GoodsImageSerializer(data = images, many = True) [4]
image_serializer.is_valid(raise_exception=True) [4]
image_serializer.save(goods = obj) [5]
headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
def perform_create(self, serializer):
return serializer.save(seller_id = self.request.user.id) # save()메서드는 생성된 object를 반환해 주기 때문에 오버라이딩하였다
모델 뷰셋을 사용하였는데 여기에서 중요한 것만 짚겠다.
post요청이 왔을 때 create메서드를 오바라이딩 하였다
request.data에서 빼와서 사용을 해도 되지만 serializer에서 접근을 하고 싶은 마음에 검색하여 사용했다.
serializer클래서 내부에서 가공되지 않은 상태의 데이터를 사용하기 위해서 initial_data를 사용하는 것으로 판단을 하였다. context에 데이터를 넘겨주어도 되지만 여기서는 굳이 그렇게 안 하고 view에서 처리하였다.