"Media" 파일 = 웹 서비스 이용자들이 업로드하는 파일
Static vs Media
Static |
Media |
이미 가지고 있는 파일들을 보여주는 것이기에 외부와 통신할 필요 없음. |
사용자가 업로드한 파일을 받아와야 하는 것이기에 외부와의 통신 필요 |
settings.py에서 static 파일이 어디에 있고, 어디로 모을지를 설정해줌. |
settings.py에서 media 파일이 어느 url을 타고, 어디로 모을지를 설정해줌. |
Media
media 파일이란 FileField 를 통해 저장한 모든 파일을 지칭합니다.
ImageField 도 FileField 를 상속받은 필드로서 해당 필드로 저장된 파일도 media 파일입니다.
이는 db 필드에는 저장경로를 저장하고 파일은 settings.MEDIA_ROOT 경로에 저장 하게 됩니다.
또 media는 외부에서 값이 들어오는 형태잖아요?
쟝고는 url을 통해 외부와 통신하기 때문에,
외부에서 값을 받아오는 media를 사용하기 위해 url 설정이 필요합니다.
1) 사용자가 이미지를 업로드 하면 이미지가 저장될 장소 설정 ->setting.py
- MEDIA_URL
MEDIA_URL = '/media/'
각 media 파일에 대한 URL 의 고정값을 설정할 수 있습니다.
http://127.0.0.1:8000/media/파일경로 형태가 되게 하기 위해서 저렇게 설정해준 것입니다.
- MEDIA_ROOT
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
미디어 파일이 저장될 경로를 설정한 부분입니다.
- “STATICFILES_DIRS는 있는데 왜 MEDIAFILES_DIRS 설정은 없죠?”
Static의 경우 개발하며 직접적으로 관리해주어야 하는 파일이지만,
Media 파일은 웹사이트 이용자가 올리는 파일이기 때문에
App 차원에서 직접 관리할 필요가 없습니다.
2) media에 파일 올리기
(1) #models.py
class Profile(models.Model):
title = models.CharField(max_lenght=255)
image = models.ImageField(upload_to='images/')
def __str__(self):
return self.title
models 에 ImageField를 통해 이미지를 받을 수 있도록 했습니다.
여기에 사용자가 업로드 한 이미지가 들어가게 되겠죠?
이때 MEDIA_ROOT 를 지정해줌으로서, 해당 경로에 이미지 사진을 저장하게 됩니다.
추가로 upload_to 옵션을 넣은 것은 BASE_DIR/media/images/아래에 저장해달라는 말입니다.
이렇게 해주는 이유는 각 이미지를 구분하여 저장하기 위함입니다.
만약 이 옵션을 사용하지 않으면 MEDIA_ROOT에서 지정해준 대로 BASE_DIR/media에 저장이 되겠죠?
(2) #터미널
이미지를 데이터베이스에 넣고 싶을 때는 다음과 같은 패키지가 필요합니다.
pip install pillow
PIL(Python Image Library)의 일종, 파이썬으로 이미지들을 처리하고 싶을 때 사용합니다.
그리고 그 다음 db에 알려줘야겠죠-?
python manage.py makemigrations
python manage.py migrate
(3) #admins.py
from .models import Profile
admin.site.register(Profile)
(4) #upload.html
<form action="{% url 'upload_create' %}" method="POST" enctype="multipart/form-data">
{% csrf_token %}
제목 <br>
<input type="text" name="title"> <br>
내용 <br>
<input type="file" name="image"><br>
<input type="submit" value="Submit" />
</form>
method 는 POST로, enctype 도 다음과 같이 설정을 해주셔야 합니다.
enctype 속성은 해당 데이터가 인코딩되는 방법을 명시합니다.
method 속성값이 “post”인 경우에만 사용할 수 있습니다.
또한 속성값이 "multipart/form-data"라는 의미는 모든 문자를 인코딩하지 않는다는 것을 명시합니다.
주로 form 요소가 파일이나 이미지를 서버로 전송할 때 주로 사용하며,
이를 설정하지 않으신다면 파일은 넘어오지 않고 파일 이름만 넘어오게 됩니다.
(5) upload.html에 view,url연결-
#views.py
def upload(request):
return render(request,'upload.html')
def upload_create(request):
form=Profile()
form.title=request.POST['title']
try:
form.image=request.FILES['image']
except: #이미지가 없어도 그냥 지나가도록-!
pass
form.save()
return redirect('/myprofile/profile/')
여기서 특이점은 파일 및 이미지를 받을 때는 request.FILES을 이용해야 한다는 점입니다.
이때 파일의 저장경로가 문자열로 db에 들어가고 실제 저장은 해당경로에 되게 됩니다.
try-except 는 예외처리를 하기 위해 넣어준 건데요.
try:
실행할 코드
except:
예외가 발생했을 때 처리하는 코드
이미지를 필수적으로 넣지 않아도, 처리할 수 있게끔 하기 위해 넣어봤습니다.
#urls.py
path('myprofile/upload/',myprofile.views.upload,name="upload"),
path('myprofile/upload_create/',myprofile.views.upload_create,name="upload_create"),
3) url
여태 url에 넣었던 것들은 웹페이지의 경로들이었습니다.
하지만 때때로 페이지뿐만 아니라 파일들도 경로가 필요합니다.
static 또한 “STATIC_URL로 설정한 폴더에 있는 이미지 파일을 가져와줘”를 통해 파일을 불러온 것입니다.
이때 static파일의 경우 서버가 어떤 경로에 어떤 파일이 있는지 알지만,
media파일의 경우 서버는 그 파일이 있는지 없는지, 그 이름은 무엇인지를 알 수 없습니다.
즉, static 파일은 쟝고에서 직접 serving 해줬지만,
media 파일은 serving하기 위한 url을 짜주어야 합니다.
개발의 편의상 서빙 Rule을 직접 짜주었습니다.
이때 static메소드를 이용해 media파일의 url과 경로를 관리해줍니다.
#urls.py
from django.conf import settings
from django.conf.urls.static import static
MEDIA_URL과 MEDIA_ROOT에 저장되어 있다는 것을 알려줘야 하니,
settings를 import 해줬습니다. 그리고 static 함수를 import 해주었네요.
(이러한 import 관련 경로들은 굳이 외우시지 않아도 됩니다.
필요할 때마다 구글링하시면 됩니다.:)
그리곤 다음 코드를 추가해줬는데요.
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
static 함수는 정적 파일들의 url을 관리하는 함수입니다.
첫 번째 인자로 Media파일의 URL을,
키워드 인자 document_root로 Media파일이 위치한 경로를 전달했습니다.
이는 “Media파일이 있으면 URL에 MEDIA_URL을 통해(-/media),
실제 파일은 MEDIA_ROOT에서 가지고와줘.”라는 의미라고 보시면 됩니다.
이때 static 함수를 urlpateerns라는 리스트에 바로 넣지 않고
+=를 한 것은 static 함수가 여러개의 url을 return 할 수도 있기 때문입니다.
4) 결과화면 보이는 profile.html
#views.py
def profile(request):
profile=Profile.objects.all()
return render(request,'profile.html',{'profile':profile})
#profile.html
{% for file in profile %}
<h1> {{file.title}} </h1>
<img src="{{ file.image.url }}">
<br><br>
{% endfor %}
file.image에서 .url을 추가한 이유에 대해서 알고 싶다면 url과 path라는 두 가지 속성에 대해 아셔야 합니다.
<!-- 1번 -->
<img src="{{ file.image }}" >
<!-- 2번 -->
<img src="{{ file.image.url }}" >
#<!-- 3번 -->
#<img src="{{ file.image.path }}" >
1번의 경우, db에는 파일의 경로가 문자열로 저장되어 있기 때문에 저 부분은 그저 문자열을 참조하게 될 것입니다.
2번과 3번은 모두 우리가 원하는 값을 받을 수 있는데,
url 은 media 폴더 부터 시작하는 상대 경로를 의미하고,
path 는 절대경로를 나타냅니다.
둘 다 media 파일을 참조하기 때문에 이미지를 불러올 수 있습니다.
#urls.py
path('myprofile/profile/',myprofile.views.profile,name="profile"),
Media 파일 처리 순서
- views에서 HttpRequest.FILES 를 통해 파일이 전달
- views,form 로직을 통해 유효성 검사 수행
- ImageField(FileField)에 문자열로 경로를 저장
- settings.MEDIA_ROOT 경로에 파일을 저장 (원한다면 AWS등의 클라우드 스토리지에도 저장이 가능합니다)
'개발 > Django_python 웹 프레임워크' 카테고리의 다른 글
Django project 4 - url 관리 (0) | 2020.07.16 |
---|---|
Django 템플릿관리, 상속 (0) | 2020.07.16 |
Django-Static, 이미지 넣기, css 적용하기 (0) | 2020.07.15 |
Network] HTTP 패킷 / Get, Post(feat. Django) (1) | 2020.07.15 |
Blog project_Create 3 : CSRF 공격(Cross Site Request Forgery) (0) | 2020.07.13 |
댓글