[Django] Media File
Media File
- 유저가 업로드하는 정적파일(Static File)
Static File 관련 참고 : [Django] Static File
- Django 의 관련 모델필드 :
FileField
,ImageField
ImageField
의 경우 Pillow 라이브러리 필요
- 업로드된 파일은 기본적으로
settings.MEDIA_ROOT
경로에 저장된다.
Pillow (Python Library)
Install Command
$ pip install Pillow
-
Django 의
ImageField
를 사용하기 위해 필요한 Python 이미지 처리 라이브러리 -
기존 Python 이미지 처리 라이브러리인 PIL (Python Image Library) 프로젝트가 정지되며 PIL을 Fork 하여 진행중인 프로젝트
-
PIL 과 API 가 유사하다.
Model Field
FileField
-
파일 업로드 필드
-
primary_key
속성이 지원되지 않는다. upload_to
속성으로 업로드된 파일의 저장 경로를MEDIA_ROOT
하위에 지정할 수 있다.MEDIA_URL
에도 prefix 처럼 붙게된다.
- DB의 필드에는
settings.MEDIA_ROOT
의 하위 경로를 String 으로 저장
ImageField
-
FileField
를 상속받은 필드 -
업로드된 파일이 이미지인지 유효성 검사를 한다.
Template
HTML Tag
form Tag
파일을 업로드 필드가 포함된 Form 의 경우
form 태그의 속성으로 method:"POST" enctype:"multipart/form-data"
지정해주어야 한다.
<form action="" method="POST" enctype="multipart/form-data">
input Tag
<input type="file" name="<NAME>">
input tag 에 name 속성(key)을 지정해주지 않으면 전송된 데이터를 인식하지 못한다.
django.forms
를 상속받은 Form 클래스의 경우
name 의 값은 자동으로 해당 클래스의 필드네임으로 할당된다.
Get Relative URL By url
template 에서 FileField 에 해당하는 속성의 URL을 가져오기 위해서는 .url
을 붙여주면 된다.
<img src="{{ TmpUser.photo.url }}">
{{ TmpUser.photo.url }}
은 <settings.MEDIA_URL>/TmpUser.photo
와 같은 값을 반환한다.
이에따라 settings.MEDIA_URL
을 /media/
로 할당하였다면
{{ TmpUser.photo.url }}
의 값은
"/media/{{ TmpUser.photo.url }}"
이 된다.
FileField 의
url
메서드는 FileField 의 storage 에 할당되는 기본값을 살펴보면
작동원리를 파악할 수 있다.
settings.py
MEDIA_ROOT
-
유저가 업로드한 파일(Media File)이 저장될 경로
-
settings.py
에서 변수MEDIA_ROOT
에 새로운 경로를 할당함으로써 설정 가능하다.
Example
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
- 설정된
MEDIA_ROOT
를 다른 Python Script 에서 불러오고 싶은 경우, 아래와 같이 할 수 있다.
from django.conf import settings
media_path = settings.MEDIA_ROOT # settings.py 의 MEDIA_ROOT 를 media_path 라는 변수에 할당
MEDIA_URL
-
유저가 업로드한 파일(Media File)의 기본 URL
-
settings.py
에서 변수MEDIA_URL
에 새로운 값을 할당함으로써 설정 가능하다. -
끝에
/
를 붙여준다.
Example
MEDIA_URL = '/media/'
Serving Media File During Development
Media File 은 Static File 과는 다르게 Django 의 개발단계(DEBUG=True
)에서 기본으로 serving 해주지 않는다.
따라서 개발단계에서 Media File을 serving 받기 위해서는 추가적인 설정을 해줄 필요가 있다.
settings.py
를 아래와 같이 설정한 것으로 가정하겠다.
settings.py
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
static Method
urls.py
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
. . .
]
urlpatterns += static(
prefix=settings.MEDIA_URL,
document_root=settings.MEDIA_ROOT,
)
Django 에서 제공하는 static
메서드로 Media File 을 개발단계에서도 serving 이 되도록 설정한 것이다.
static
메서드는 DEBUG=True
일 때만 유효하다. DEBUG=False
가 되면 빈 리스트를 반환한다.
Make Oneself (Not Using static Method)
static
메서드를 사용하지 않는다면 아래와 같은 작업을 진행해야한다.(권장 X)
urls.py
from django.urls import path
from . import views
urlpatterns = [
path('media/<path:path>/', views.media_serve, name='media_serve'),
]
settings.py
에서 MEDIA_URL
을 '/media/'
로 설정했기 때문에
urlpattern 에서 media 로 시작하는 경로(MEDIA_URL
)는
media_serve
뷰 함수를 반환하도록 설정하였다.
views.py
from django.http import FileResponse
from django.conf import settings
import os, mimetypes
def media_serve(request, path):
file_path = os.path.join(settings.MEDIA_ROOT, path)
return FileResponse(open(file_path, 'rb'), content_type=mimetypes.guess_type(file_path)[0])
media_serve
뷰 함수는 media/<path:path>/
의 path 라고 네이밍된 경로를 반환받은 뒤,
MEDIA_ROOT
와 합쳐서 file_path
로 할당한다. 이후 FileResponse
를 통해 해당 파일을 반환한다.
이 때, content_type
은 mimetypes.guess_type
메서드를 통해 파일의 타입을 자동으로 반환받은 값을 전달한다.
mimetypes.guess_type
은 요소가 두개인 Tuple 을 반환한다.
content_type
에 구체적인 값을 명시하기 위해 인덱스가 0인 값을 지정해주었다([0]
).
인덱스를 지정안하고, 튜플을 전달해도 문제없이 작동하긴 한다.
브라우저의 개발자 도구에서 content_type
을 확인해보았을 때,
인덱스를 지정해서 전달한 값과 튜플로 전달한 값 각각 그대로 전달받은 것을 알 수 있다.
둘 다 문제없이 인식하는 것을 보았을 때 브라우저에서 두가지 값을 모두 자동으로 인식해주는 것 같다.
<path:path>
에서 왼쪽의 path 는 Path converter 중 하나를 의미한다. (일종의 Type)
오른쪽의 path 는 view 함수의 path 인수로 전달할 값(경로)에 해당한다.
관련 참조 : Django Documentation - URL dispatcher: Path converters
Leave a comment