728x90
반응형
Django 프로젝트에서 이미지 핸들링하기
이미지 파일을 DB 에 저장하기엔 용량이 크기 떄문에 클라우드 Object Storage 에 저장해서 url 로 가져다 쓴다.
NPC 는 관련해서 AWS S3 호환 서비스 Object Storage 를 제공하고 있기 떄문에 사용해보려고 한다.
AWS S3
AWS boto3 를 이용한 파일 업로드
boto3 는 AWS 를 위한 Python SDK (Software Development Kit) 이다. 사용하면 AWS 서비스에 쉽게 액세스 할 수있다. NCP 의 Object Storage 와 같은 S3 호환 서비스에도 사용이 가능하다.
간단한 사용 방법
HTTP/HTTPS 호출 도메인 #Korea
<https://kr.object.ncloudstorage.com>
boto 3 설치
pip install boto3
AWS 서비스에 액세스
여기에선 NCP 로 접속해야하니 NCP 의 Access key 와 Secret key 사용
import boto3
s3 = boto3.client('s3', aws_access_key_id='YOUR_ACCESS_KEY', aws_secret_access_key='YOUR_SECRET_KEY')
버킷을 조회하거나 생성
# 버킷 리스트 조회
response = s3.list_buckets()
buckets = [bucket['Name'] for bucket in response['Buckets']]
# 버킷 생성
s3.create_bucket(Bucket='my_bucket')
업로드, 다운로드, 삭제
# 파일 업로드
s3.upload_file('myfile.txt', 'my_bucket', 'myfile.txt')
# 파일 다운로드
s3.download_file('my_bucket', 'myfile.txt', 'myfile_downloaded.txt')
# 파일 삭제
s3.delete_object(Bucket='my_bucket', Key='myfile.txt')
S3 호환 스토리지 서비스 (e.g. NCP) 에서 사용할 경우 endpoint_url 사용
s3 = boto3.client('s3', endpoint_url='https://your_endpoint_url', aws_access_key_id='YOUR_ACCESS_KEY', aws_secret_access_key='YOUR_SECRET_KEY')
NCP 로 Django 서비스에 적용해보기
실제 사용 코드
# image_handler - store, menu 등에서 이미지를 핸들링 하기 위해 utils 에 생성
def image_handler(request, exsiting_post=None):
image_url = exsiting_post if exsiting_post else None
try:
if request.FILES.get("store_pic"):
folder_name = "sajjang_store"
image = request.FILES.get("store_pic")
elif request.FILES.get("menu_pic"):
print(request.FILES.get("menu_pic"))
folder_name = "sajjang_menu"
image = request.FILES.get("menu_pic")
else:
print("FILES.get ?, neither store_pic nor menu_pic")
except Exception as e:
print(e)
return JsonResponse({"error": str(e)}, status=400)
if image:
image: File
endpoint_url = settings.IMAGE_BUCKET_ENDPOINT
access_key = settings.NCP_ACCESS_KEY
secret_key = settings.NCP_SECRET_KEY
buket_name = "del-app-mh"
s3 = boto3.client(
"s3",
endpoint_url=endpoint_url,
aws_access_key_id=access_key,
aws_secret_access_key=secret_key,
)
image_id = str(uuid.uuid4())
# split 이후 마지막 값 가져오기 (jpg, png, gif 등등)
file_extension = image.name.split(".")[-1]
image_name = f"{image_id}.{file_extension}"
s3_key = f"{folder_name}/{image_name}"
try:
s3.upload_fileobj(image.file, buket_name, s3_key)
s3.put_object_acl(ACL="public-read", Bucket=buket_name, Key=s3_key)
except Exception as e:
print(e)
return JsonResponse({"error": str(e)}, status=400)
image_url = f"{endpoint_url}/{buket_name}/{s3_key}"
print("image_url out:", image_url)
return image_url
# post 메서드에서 image_handler 를 불러와 적용
def post(self, request):
image_url = image_handler(request)
try:
name = request.POST["store_name"]
address = request.POST["store_address"]
store_pic = image_url if request.FILES.get("store_pic") else None
status = request.POST.get("status", False)
user = get_object_or_404(User, id=request.user.pk)
category = get_object_or_404(Category, id=request.POST["category"])
new_store = Stores(
user_id=user,
name=name,
address=address,
store_pic=store_pic,
category_id=category,
status=status,
)
new_store.save()
return redirect("sajjang:sajjang_home")
except Exception as e:
return JsonResponse({"error": str(e)}, status=400)
{% comment %} url 로 저장되어 있기 때문에 바로 적용 {% endcomment %}
<div class="my-2" style="width:100px; height:100px;">
{% if store.store_pic %}
<img src="{{ store.store_pic }}" class="rounded float-start bg-secondary" alt="" style="width:100px; height:100px;">
{% else %}
<img src="..." class="rounded float-start bg-secondary" alt="No img" style="width:100px; height:100px;">
{% endif %}
</div>
728x90
반응형
'Dev. > Django & DRF' 카테고리의 다른 글
Django: select_related, prefetch_related, only & defer (0) | 2023.11.10 |
---|---|
Django: mysqlclient connection (1) | 2023.11.04 |
Django: ‘WSGIRequest' object has no attribute 'data' (0) | 2023.10.18 |
[Cloud] Django: Code develop for TEST2 (0) | 2023.08.31 |
Django : DRF 적용하기3 - Spectacular (0) | 2023.08.16 |
댓글