Django rest framework 다중 이미지 업로드 방법
중첩된 Serializer, 한 게시물에 여러 이미지 올리기!
다중 이미지 업로드 처리부분에 대해 구글링을 해봤을 때 DRF serializer 에 대한 내용보다 django forms에 대한 내용과 stack overflow 글이 많이 나왔고, 국내 개발자분들이 정리한 포스팅이 얼마 없어서 제가 기록도 할 겸 정리해보고자 합니다.
먼저 저는 1개의 포스팅 글이 여러 이미지를 가지고 있는 1:N 구조의 모델을 생성했습니다.
# models.pyclass Post(models.Model):
text = models.CharField(max_length=500)
location = models.CharField(max_length=100)class PostImage(models.Model):
post = models.ForeignKey(Post, on_delete=models.CASCADE)
image = models.ImageField(upload_to="post/%Y/%m/%d")
Post를 외래키로 하는 이미지 모델을 생성하고 Post가 삭제될 시 같이 삭제 될 수 있도록 CASCADE 옵션을 추가해주었습니다.
# serializers.pyfrom rest_framework import serializers
from .models import Post, PostImageclass PostImageSerializer(serializers.ModelSerializer):
class Meta:
model = PostImage
fields = ['image']class PostSerializer(serializers.ModelSerializer):
images = PostImageSerializer(many=True, read_only=True)
class Meta:
model = Post
fields = ['id', 'text', 'location', 'images'] def create(self, validated_data):
images_data = self.context['request'].FILES
post = Post.objects.create(**validated_data)
for image_data in images_data.getlist('image'):
PostImage.objects.create(post=post, image=image_data)
return post
Serializers.py 에는 이미지를 직렬화할 PostImageSerializer을 두고, Post에서 글과 이미지를 한번에 입력받아서 저장할 것이기 때문에 PostImageSerializer를 images 변수를 두어 가져옵니다.
여기서 many=True 옵션은, 저희는 이미지를 여러개 가져와서 다중으로 업로드하고 싶은 것이기 때문에 준 것이고,
기본적으로 중첩된 Serializer 에서는 쓰기(Create), 갱신(Update)를 지원해주지 않습니다. 그렇기 때문에 read_only=True 옵션을 주었습니다.
create 메소드에서는 파일 형식으로 전달받은 데이터틀 images_data에 따로담아놓고 post 객체를 생성합니다.
images_data 변수 안에 담겨 있는 image 리스트들을 .getlist(‘image’) 를 통해서 접근하여 for문으로 image_data를 하나씩 꺼내옵니다.
그 후 좀 전에 생성한 post 객체와, image_data를 PostImage 객체에 담아 생성합니다.
# views.pyfrom rest_framework.viewsets import ModelViewSet
from .serializers import PostSerializer
from .models import Postclass PostViewSet(ModelViewSet):
queryset = Post.objects.all()
serializer_class = PostSerializer# urls.pyfrom django.urls import path, include
from rest_framework.routers import DefaultRouter
from . import viewsrouter = DefaultRouter()
router.register('posts', views.PostViewSet)urlpatterns = [
path('', include(router.urls)),
]
views.py 에서는 ModelViewSet 을 이용했구요.
urls.py에서 router를 통해 연결해주었습니다.
Postman을 통해 POST 요청으로 text와 location을 문자열값으로 주시고, image라는 키값을 가지는 파일 여러개를 업로드해서 POST 요청으로 데이터를 보내시면 정상적으로 값이 저장되는 것을 보실 수 있습니다.
도움이 되셨으면 좋겠습니다. 감사합니다.