티스토리 뷰

django

django / 사진 업로드 (media)

4567은 소수 2020. 12. 25. 02:00

텍스트만 올리면 재미없으므로 사진 첨부를 해보도록 하겠습니다.

여담으로, 현재 혼자 진행하는 프로젝트는 블로그에 올린 글보다 더 많은 기능이 들어가있어, 기본 틀만 정리하여 올린 뒤, 혼자 진행하는 프로젝트에 이어서 추가 내용을 포스팅하겠습니다. (생각보다 구현한게 꽤 많더라구요...)

 

사진과 같은 파일은 static 파일과 media 파일로 나누어집니다.

static 파일은 관리자가 기본으로 딱 보여지게 하는, 사이트에 접속하면 누구나 보이는 로고와 같은 이미지가 static 파일입니다.

media 파일은 사용자가 업로드할 수 있는 파일입니다. 제가 블로그 글을 쓴다면 사진을 업로드할 수 있고, 그 업로드된 사진이 media 파일입니다.

 

media 파일 업로드 하는 방법만 살펴보도록 하겠습니다.

 

우선 설정할 것이 필요합니다.

settings.py 가장 마지막에 다음을 추가합니다. (STATIC_URL 은 가장 밑에 있을 것입니다. 그 밑에 두 줄 추가하면 됩니다.) 그리고 os는 처음에 settings.py에 import 되어있지 않으므로 import os 를 제일 위에 추가해줍니다.

STATIC_URL = '/static/'

MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

 

그 다음 사용하고자 하는 앱의 urls.py에서 다음과 같이 추가해 줍니다.

from django.conf import settings
from django.conf.urls.static import static

urlpatterns = [
  # path 경로들
] + static(settings.MEDIA_URL, document_root = settings.MEDIA_ROOT)

static 파일을 MEDIA_URL로 지정한 media 디렉토리에서 가져오겠다는 것입니다. 

그렇다면 media라는 디렉토리 또한 필요하겠지요. 

프로젝트 디렉토리에서 현재 구현 중인 app과 동일한 루트를 가지도록 media 폴더를 만들어줍니다. 그리고 그 아래에 images라는 폴더를 하나 추가해줍니다. (images에 media 파일을 저장할 것입니다.)

이제 모델을 수정하면 기본 설정이 마무리됩니다.

models.py로 가서 기존의 Post 모델에 다음을 추가합니다.

class Post(models.Model):
  # 생략
  image = models.ImageField(upload_to = "images/", null=True, blank=True)

  def __str__(self):
    return str(self.title)

( def __str__(self) 부분은 admin 모드로 보았을 때 제목으로 파일을 구분할 수 있게 하는 것입니다. 설정을 안해놓았더군요 ㅎㅎㅎ )

Post 모델의 image를 ImageField를 이용해 imges라는 디렉토리 아래에 업로드 시킵니다. null과 blank 값을 True로 default로 설정함으로써 이미지가 업로드되어야 글이 저장되도록 만듭니다. 이미지가 없어도 글이 저장되게 하기 위해서는 views.py에서 create 함수의 image 부분에서 예외처리를 해주면 됩니다.

 

이제 위 모델을 makemigration 하면 뭔가를 설치해라고 할 것입니다. pillow 모듈을 설치하고 업데이트를 하라는 데로 한 뒤 다시 migrate 과정을 거치면 됩니다.

 

이제 views.py를 살펴보겠습니다.

def create(request):
  if request.method=="POST":
    post = Post()
    post.title = request.POST['title']
    post.body = request.POST['body']
    post.date = timezone.now()
    post.image = request.FILES['image']
    post.save()
    return redirect('/detail/'+str(post.id),{'post':post})
  else:
    post = Post()
    return render(request,'create.html',{'post':post})

예외처리를 하지 않아 이대로 하면 이미지 업로드 없이 글 저장을 하면 에러가 납니다. 그러므로 예외처리를 다음과 같이 하여도 되고, 위 모델을 정의할 때 null과 blank를 조정하여 처리해도 됩니다.

try:
	post.image = request.FILES['image']
except:
	post.image = None

이제 마지막으로 html을 수정합시다.

사진을 필요로 하는 html이 create와 detail 부분이므로 여기만 수정해주면 됩니다.

{% extends 'base.html' %}
{% block content %}
  <div class="container">
  <form method="POST" enctype="multipart/form-data">
    {% csrf_token %}
    제목 : 
    <input name="title" type="text" value="">
    <br><br>
   
    내용 :
    <textarea cols=50 rows=20 name="body"></textarea>
    <br><br>
  
    업로드 : 
    <input name="image" type="file">
    <br><br>

  <input class="btn btn-primary" type="submit" value="글 작성">
  </form>
  </div>
{% endblock %}

create.html에서 기존의 form 태그에 enctype 부분을 추가해줍니다. 저 부분을 추가하지 않으면 파일의 제목만 저장되고, 이미지는 저장되지 않습니다.

{% extends 'base.html' %}
{% block content %}
<div class="container">
  <h1>제목 - {{post.title}}</h1><br>
  날짜 - {{post.date}}<br>
  본문 - {{post.body}}<br>
  {% if post.image %}
    <img src="{{post.image.url}}">
    <br><br>
  {% endif %}
</div>
{% endblock %}

detail.html에서 post.image 가 존재할 시 img 태그를 이용해 이미지가 저장된 url로부터 해당 파일을 불러옵니다.

 

이제 결과를 살펴봅시다.

이렇게 사진을 업로드 잘 할 수 있고,

사진 업로드가 안되어도 글이 잘 저장됩니다.

 

'django' 카테고리의 다른 글

django / 댓글 기능 구현  (0) 2020.12.25
django / 글 수정, 삭제  (0) 2020.12.25
django / 새 글 작성  (0) 2020.12.25
django / url 관리  (0) 2020.12.04
django / base.html 만들기 (템플릿 상속)  (0) 2020.12.03
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
TAG
more
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
글 보관함