반응형
Django에서 user와 profile_image가 1대 1 관계일 때 이미지를 경로에 저장하는 방법이다. - 이후 DB에 저장하려면 프론트로 보낸 URL을 DB에 저장하면 된다.
UpdateAPIView를 상속 받아서 사용하였고 UpdateAPIView에는 PUT과 PATCH가 있는데 나는 PUT 만 사용할 예정이었기 때문에 allowed_methodes를 추가하여 주었다.
DRF에서는 파일 찾기로 파일을 보내는게 정상적으로 잘 되었는데 스웨거에서는 자꾸 파일을 FILE 이라는 JSON형식으로 받아서 많은 시간을 소비하였는데 APIView를 UpdateAPIView로 변경하니깐 바로 정상적으로 작동되었다.
아마 APIView에서 파라미터로 원하는 값이 JSON형식이여서 스웨거에서 자동으로 그렇게된 것 같다.
전체 코드
import uuid
from django.conf import settings
from django.core.files.storage import FileSystemStorage
from rest_framework import serializers
from rest_framework.generics import UpdateAPIView
from rest_framework.parsers import MultiPartParser
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework_simplejwt.authentication import JWTAuthentication
class ProfileImageSerializer(serializers.Serializer):
profile_image = serializers.ImageField()
class ProfileImageAPI(UpdateAPIView):
serializer_class = ProfileImageSerializer
authentication_classes = [JWTAuthentication]
permission_classes = [IsAuthenticated]
parser_classes = (MultiPartParser,)
allowed_methods = ["PUT"]
def put(self, request, *args, **kwargs):
image_file = request.FILES.get("profile_image")
if not image_file:
return Response({"error": "No image Files"}, status=400)
fs = FileSystemStorage(location=settings.MEDIA_ROOT)
random_filename = f"profile_images/user/{uuid.uuid4()}.webp"
filename = fs.save(random_filename, image_file)
file_url = fs.url(filename)
return Response({"file_url": file_url}, status=200)
코드 설명
class ProfileImageSerializer(serializers.Serializer):
profile_image = serializers.ImageField()
class ProfileImageAPI(UpdateAPIView):
serializer_class = ProfileImageSerializer
authentication_classes = [JWTAuthentication]
permission_classes = [IsAuthenticated]
parser_classes = (MultiPartParser,)
allowed_methods = ["PUT"]
ProfileImageSerializer 클래스는 Django의 serializers.Serializer를 상속받아 데이터 타입을 변환해 주었다.
ProfileImageAPI 클래스
- serializer_class - 이 뷰에서 사용할 시리얼 라이저 클래스를 지정한다.
- authentication_class - API 엔드포인트에 대한 사용자 인증 방법을 지정한다. 위에서는 JSON Web Token을 사용하였다.
- parser_class - 클라이언트가 요청을 보낼 때 사용할 파서 클래스를 지정한다. 위에서는 이미지를 받기 위해서 멀티 파서를 사용했다. 이 부분이 스웨거에서 이미지를 파일 찾기로 받기 위해서 중요한 부분이다. 실제로 많이 헤맨부분이다.
- allowed_methodes - 위에서 설명했듯 엔드포인트에 허용되는 HTTP 메서드이다. PUT 만 사용할 것이기 때문에 PUT 만 넣어주었다.
def put(self, request, *args, **kwargs):
image_file = request.FILES.get("profile_image")
if not image_file:
return Response({"error": "No image Files"}, status=400)
fs = FileSystemStorage(location=settings.MEDIA_ROOT)
random_filename = f"profile_images/user/{uuid.uuid4()}.webp"
filename = fs.save(random_filename, image_file)
file_url = fs.url(filename)
return Response({"file_url": file_url}, status=200)
클라이언트가 전송한 파일을 서버에 저장하고 저장된 URL을 리턴해주는 구문이다.
- image_file = request.FILES.get("profile_image"): 클라이언트로부터 전송된 파일을 얻는다.
- if not image_file : 전송된 파일이 없으면 에러를 리턴한다. (상태코드 400)
- fs = FileSystemStorage(location=settings.MEDIA_ROOT) : 파일 저장을 위한 파일 시스템 스토리지 객체를 생성한다.
- filename = fs.save(random_filename, image_file) : image_file을 random_filename으로 저장한다.
- return Resopnse({"file_url": file_url}, status=200) : file_url을 리턴한다. (상태코드 200)
반응형
'Django > DRF' 카테고리의 다른 글
Django JWT를 이용한 소셜로그인 (백엔드) (0) | 2023.10.11 |
---|---|
DRF JWT를 이용하여 유저 정보 GET/POST (0) | 2023.10.11 |
Django 인기글 구현 (1) | 2023.09.26 |
클라우드 타입으로 Django, postgreSQL 서버 배포 (1) | 2023.08.09 |
Django의 OneToOneField와 ForeignKey의 차이점 (0) | 2023.05.23 |