사진이나 미디어를 유저들이 업로드하는데, 아무런 조치 없이 업로드할 순 없습니다. 이번 파트에서는 user upload에 관해 다루어보겠습니다.
MEDIA_ROOT
어디에다 우리가 업로드한 파일을 써야 할 지 말해주는 곳입니다.
settings.py에 MEDIA_ROOT = BASE_DIR / "uploads"
합니다. 그 후 파일을 업로드하면 uploads라는 폴더가 생성된 것을 확인할 수 있습니다. gitignore에 uploads/를 추가해 사진 파일들이 업로드되지 않도록 합니다.
django 3.1 미만의 버전으로 startproject하면 TypeError: unsupported operand type(s) for /: 'str' and 'str'오류가 발생할 수 있으므로 버전확인을 합니다.
다음의 코드를 분석합니다.
class Photo(core_models.TimeStampedModel):
caption = models.CharField(max_length=80)
file = models.ImageField(upload_to="room_photos") # room_photos라는 폴더에 사진 저장됨
room = models.ForeignKey("Room", related_name="photos", on_delete=models.CASCADE)
def __str__(self):
return self.caption
file은 upload_to를 사용해 저장하려는 경로를 지정해주었는데요! 이로써 uploads/room_photos
에 저장됩니다. migrate는 필수!
그!러!나! 저장은 원하는 대로 잘 되지만 관리자 페이지에서 사진링크파일을 열면 장고가 사진위치에 접근할 수 없다고 말하는데요~
url을 내 컴퓨터 안의 폴더와 연결해야 장고가 해당 위치에 접근가능합니다.
MEDIA_URL은 MEDIA_ROOT에서 온 MEDIA를 다룹니다. settings.py에 MEDIA_URL = "media/"
를 입력합니다. 만약 uploads폴더로부터 사진을 가져오고 싶다면 /media/room_photos/
에 접근해야 합니다. 그래서 uploads 디렉토리를 MEDIA_URL과 연결합니다.
연결을 완료하면 내가 어디에 있는지에 따라 상대적인 상대경로로 url을 만들어줍니다. 하지만 Root에 있는 것이 원하는 것이므로 MEDIA_URL = "/media/"
로 만들어줍니다. '/media/'는 절대경로로 만들어줍니다. 그러나 Page not found에러를 보여줍니다.
에러를 보면 Using the URLconf defined in config.urls
라고 나옵니다.
이제 절반왔습니다. urlpatterns에 새로운 static 경로를 등록해주면 이 여정은 끝이 납니다.
장고가 사진을 어디에 저장해야 하는지 알고, 어떤 url에서 사진을 찾을 수 있는지 알고 있습니다. 이제는 장고에게 사진을 보여달라고 말해야 합니다.
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
path("", include("core.urls", namespace="core")),
path("rooms/", include("rooms.urls", namespace="rooms")),
path("admin/", admin.site.urls),
]
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
config/settings.py에서 from django.conf import settings
를 합니다. settings을 임포트함으로서 변경된 부분이 settings.py에 자동적으로 반영됩니다.
다음으로 static을 사용해 경로를 등록합니다. settings.DEBUG
이 True일 때 작동되도록 한 것으로 Amazon이나 Heroku에선 다른 저장소에 의해 사진이 제공되므로 이처럼 작동되는 것을 원치 않습니다. 그렇지 않으면 코드 서버에서 더 많은 디스크 공간을 소비하게 됩니다.
위 방법은 개발 모드에서만 작업된 부분으로 배포 때는 Amazon s3의 다른 저장소에 저장되도록 합니다!
from django.utils.html import mark_safe
@admin.register(models.Photo)
class PhotoAdmin(admin.ModelAdmin):
list_display = ("__str__", "get_thumbnail")
def get_thumbnail(self, obj):
return mark_safe(f'<img width="50px" src="{obj.file.url}" />')
get_thumbnail.short_description = "Thumbnail"
그냥 사진파일의 url을 입력하면 장고는 security에 의해 스크립트가 실행되지 않도록 되어있습니다. 따라서 mark_safe로 안전하다고 선언한 후 스크립트를 실행합니다.