장고와 DRF를 실습하는 중 이미지 경로에 대해서 헷갈렸다.
내가 accounts/models.py
에서 User
를 커스텀을 아래와 같이 한다면,
from django.db import models
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
email = models.EmailField('이메일', unique=True)
username = models.CharField('닉네임', max_length=150)
profile_image= models.ImageField('프로필 이미지', upload_to='profile_images/')
여기서 profile_image
의 upload_to
의 profile_images/
는 ?
upload_to
= 경로 라고 생각하면 된다.
settings
에서 지정해둔
MEDIA_URL = '/media/' # 업로드된 파일의 URL 경로
MEDIA_ROOT = BASE_DIR / 'media' # 파일 저장 경로
이 경로에 접근 할 수 있도록
메인프로젝트의 urls.py
에 아래와 같이 설정 해 줘야 한다.
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
# 기존 URL 패턴
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
그럼 위와같이 user모델의
profile_image= models.ImageField('프로필 이미지', upload_to='profile_images/')
이렇게 지정된 경로에는 파일이
/<프로젝트 루트>/media/profile_images/
이 루트에 파일명과 함께 저장이 된다!
def product_image_path(instance, filename):
return f'product_images/{instance.user.username}/{filename}'
이렇게 함수를 따로 만들어서 모델을 형성할때, upload_to
를 지정한다면 사용자별로 파일 경로를 구조화하고 중복 파일 이름 문제를 방지할 수 있다. 이 함수는 업로드된 파일의 경로를 특정 기준에 따라 동적으로 생성된다.
위 함수의 경로는 instance.user.username
을 사용하여 사용자별 디렉토리를 생성한다.
사용자 홍길동
이 product.jpg
이란 파일 이름을 업로드 한다면
product_images/홍길동/product.jpg
이 경로에 파일이 저장되어 같은 이름의 파일을 관리하기 쉽다.
instance
는 장고에서 약속한 모델 인스턴스를 참조하기 위함이고 위와같이 사용할때 상품의 정보를 포함한 사용자 데이터(instance.user.username
)를 가져온다!
이미지를 클라이언트가 넣도록 설정하고, 넣은 이미지를 서버에서 저장하도록 하는 흐름을 만들기 위해서는
MEDIA_URL = '/media/'
MEDIA_ROOT = BASE_DIR / 'media'
위와같이 MEDIA_ROOT를 설정했다면, 프로젝트 루트에 media
폴더를 생성해야 한다.
url
도 같이 세팅했기에 올린 파일에 접근하려면
http://<your-domain>/media/<uploaded_file_path>
위와같은 경로로 접속하면 클라이언트가 올린 혹은 저장된 파일에 접근이 가능하다. 따라서 ROOT를 설정할때 URL도 설정하면 편하다.
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
# 기존 URL 패턴
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
def product_image_path(instance, filename):
return f'product_images/{instance.user.username}/{filename}'
class User(AbstractUser):
profile_image= models.ImageField('프로필 이미지', upload_to=product_image_path)