3.media 파일을 다루는 방법
media 파일을 다루는 방법
Static & Media 파일
- Static 파일
- 개발 리소스로서의 정적 파일 (js, css, image 등)
- 앱 / 프로젝트 단위로 저장/서빙
- Media 파일 (django에만 존재하는 용어)
- FileField / ImageField를 통해 저장한 모든 파일 (model field)
- FileField : File Storage API를 통해 파일 저장(django는 File System Storage만 지원, django-storages를 통해 확장 지원)
- ImageField : Pilow를 통해 이미지 width/height 획득
- DB필드에는 저장경로를 저장하며, 파일은 파일 스토리지에 저장
실제로 문자열을 저장하는 필드(중요)
- 프로젝트 단위로 저장/서빙
- FileField / ImageField를 통해 저장한 모든 파일 (model field)
Media 파일 처리 순서
- HttpRequest.FILES를 통해 파일 전달
- view 로직이나 form 로직을 통해 유효성 검사 수행
- FileField / ImageFiel 필드에 경로(문자열)를 저장
- settings.MEDIA_ROOT 경로에 파일 저장
기본 settings
- MEDIA_URL: 어떤 URL을 통해 접근하는지 결정
- MEDIA_ROOT: 실제 파일을 저장할 ROOT 경로(클라우드 기반 가능)
# .settings
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
개발환경에서의 media 파일 서빙
- static 파일과 다르게, 장고 개발서버에서 서빙 미지원
- 개발 편의성 목적으로 직접 서빙 Rule 추가 가능
# .urls
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
path('admin/', admin.site.urls),
path('blog/', include('blog1.urls')),
path('instagram/', include('instagram.urls')),
]
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
admin 설정
@admin.register(Post)
class PostAdmin(admin.ModelAdmin):
list_display = ['id', 'photo_tag', 'message', 'is_public', 'message_length', 'created_at', 'updated_at']
list_display_links = ['message']
list_filter = ['created_at', 'is_public']
search_fields = ['message'] # 검색기능
def photo_tag(self, post):
if post.photo: # 장고 쉘에서 해당 파일이 없을 수도 있기 때문에 if문 처리
return mark_safe(f'<img src="{post.photo.url}" style="width: 72px" />') # mark_safe로 감싸주지 않으면 사진을 노출시키지 않음
return None
모델필드 예시
- 파일 저장시 upload_to 함수를 호출하여 저장경로를 계산
- 인자 유형
- 문자열로 지정 : “중간 디렉토리 경로”로서 활용
- 함수로 지정 : “중간 디렉토리 경로” 및 “파일명”까지 결정 가능
class Post(models.Model):
author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
message = models.TextField()
photo = models.ImageField(blank=True, upload_to='instagram/post/%Y/%m/%d') # 1폴더에 파일이 몰리는 것을 방지 uload_to
tag_set = models.ManyToManyField('Tag', blank=True)
is_public = models.BooleanField(default=False, verbose_name='공개여부')
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
uuid를 통한 파일명 정하기
# utils.py
import os
from uuid import uuid4
from django.utils import timezone
def uuid_name_upload_to(instance, filename):
app_lebel = instance.__class__._meta.app_label # 앱 이름
cls_name = instance.__class__.__name__.lower() # 모델 이름
ymd_path = timezone.now().strftime('%Y/%m/%d') # 업로드하는 연/월/일
uuid_name = uuid4().hex # 랜덤 문자열
extension = os.path.splitext(filename)[-1].lower() # 소문자 형식의 확장자 추출
return '/'.join([
app_label,
cls_name,
ymd_path,
uuid_name[:2],
uuid_name + extension,
])
File Upload Handler
- 기본적으로 파일크기 2.5MB 이하일 경우
- 메모리에 담겨 전달
- 파일크기가 2.5MB 초과일 경우
- 디스크에 담겨 전달
관련설정 settings.FILE_UPLOAD_MAX_MEMORY_SIZE
댓글남기기