본문 바로가기
Study/Django

[Django] Django에서 이미지 파일 업로드 및 제공, 수정 기능 추가하기

by ngool 2024. 9. 28.

본 포스트는 Django에서 이미지 파일을 사용자로부터 업로드 받고, 업로드 받은 파일을 사용자에게 제공 및 수정하는 기능을 추가하는 방법을 정리한 것입니다.

 

그 과정을 순서대로 알아봅시다!


사전 준비 사항

1. settings.pyMEDIA_ROOT, MEDIA_URL 설정

  • MEDIA_ROOT : 미디어 파일들이 위치하는 디렉토리의 절대 경로
  • MEDIA_URL : MEDIA_ROOT에서 제공되는 미디어 파일에 대한 주소를 생성
# settings.py

MEDIA_ROOT = BASE_DIR / 'media'
MEDIA_URL = 'media/'

 

2. 작성한 MEDIA_ROOT와 MEDIA_URL에 대한 URL 지정

  • 업로드 된 파일의 URL == settings.MEDIA_URL
  • MEDIA_URL을 통해 참조하는 파일의 실제 위치 == settings.MEDIA_ROOT

crud는 프로젝트 폴더 이름


이미지 업로드 기능

1. blank=True 속성을 작성해 빈 문자열이 저장될 수 있도록 제약 조건 작성

⇒ 게시글 작성 시 이미지 업로드 없이도 작성 할 수 있도록 하기 위함

기존 필드 사이에 작성해도 실제 테이블 생성 시에는 가장 우측(뒤)에 추가 됨

 

2. pillow 라이브러리 install 및 migration 진행

$ pip install pillow
$ pip freeze > requirements.txt

⇒  ImageField를 사용하려면 반드시 pillow 라이브러리가 필요

 

3. migration 진행

$ python manage.py makemigrations
$ python manage.py migrate

 

4. form 태그에 encytype 속성 추가

encytype : 데이터 전송 방식을 결정하는 속성

 

5. ModelForm의 2번째 인자로 요청 받은 파일 데이터 작성

  • ModelForm의 상위 클래스 BaseModelForm의 생성자 함수는 2번째 위치 인자파일을 받도록 설정되어 있음

ModelForm의 2번째 인자에 request.FILES 추가

 

6. 이미지 업로드 후 결과 확인

데이터베이스 연결 후 확인 가능


업로드 이미지 제공 기능

url 속성을 통해 업로드 파일의 경로 값을 얻을 수 있습니다!

  • article.image.url : 업로드 파일의 경로
  • article.image : 업로드 파일의 파일 이름
<!-- articles/detail.html -->

{% if article.image %}
  <img src="{{ article.image.url }}" alt="img">
{% endif %}
이미지를 업로드하지 않은 게시물은 detail 템플릿을 렌더링 할 수 없습니다.
따라서 이미지 데이터가 있는 경우에만 이미지를 출력할 수 있도록 위와 같이 if로 처리해줘야 합니다.

업로드 이미지 수정 기능

1. 수정 페이지 form 요소에 enctype 속성 추가

 

2. update view 함수에서 업로드 파일에 대한 추가 코드 작성

 

=> 여기서 instance 속성을 줘야 기존 내용이 적힌 상태로 수정 페이지가 보여지게 됩니다!


미디어 파일 추가 경로 설정

upload_to 속성을 사용하면 다양한 추가 경로 설정이 가능합니다!

# 1. 기본 경로 설정
image = models.ImageField(blank=True, upload_to='images/')

# 2. 업로드 날짜로 경로 설정
image = models.ImageField(blank=True, upload_to='%Y/%m/%d/')

# 3. 함수 형식으로 경로 설정
def articles_image_path(instance, filename):
    return f'images/{instance.user.username}/{filename}'
   
image = models.ImageField(blank=True, upload_to=articles_image_path)