데이터 분석 기술 블로그

Django에 대하여(18)_Media files 본문

백엔드

Django에 대하여(18)_Media files

데이터분석가 이채은 2024. 4. 9. 20:42

Media Files

사용자가 웹에서 업로드하는 정적파일로 user-uploaded라고 합니다.

 

1. 이미지 업로드

ImageField()

이미 업로드에 사용하는 모델 필드로 이미지 객체가 직접 저장되는 것이 아닌 '이미지 파일의 경로'가 문자열로 DB에 저장됩니다.

1.1 settings.py에 MEDIA_ROOT, MEDIA_URL 설정

MEDIA_ROOT란 미디어 파일들이 위치하는 디렉토리의 절대 경로입니다.

# settings.py

MEDIA_ROOT = BASE_DIR / 'media'

MEDIA_URL이란 MEDIA_ROOT에서 제공되는 미디어 파일에 대한 주소를 생성하는 것입니다. STATIC_URL과 동일한 역할을 한다고 생각하면 됩니다.

# settings.py

MEDIA_URL = 'media/'

업로드된 파일의 URL == settings.MEDIA_URL

위 URL을 통해 참조하는 파일의 실제 위치 == settings.MEDIA_ROOT

# crud/urls.py

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

urlpatterns = [
    path('admin/', admin.site.urls),
    path('articles/', include('articles.urls')),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

 

1.2 이미지 업로드

black = True 속성을 작성해 빈 문자열이 저장될 수 있도록 제약 조건을 설정합니다. 기존 필드 사이에 작성해도 실제 테이블 생성 시에는 가장 우측(뒤)에 추가됩니다.

# articles/models.py

class Article(models.Model):
    title = models.CharField(max_length=10)
    content = models.TextField()
    image = models.ImageField(blank=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

migration을 진행합니다. ImageField를 사용하려면 반드시 Pillow 라이브러리가 필요합니다.

pip install pillow

python manage.py makemigrations
python manage.py migrate

pip freeze > requirements.txt

form 요소의 enctype 속성을 추가합니다.

<!-- articles/create.html -->

<h1>CREATE</h1>
<form action="{% url 'articles:create' %}" method="POST" enctype="multipart/form-data">
  {% csrf_token %}
  {{ form.as_p }}
  <input type="submit">
</form>

vie 함수에서 업로드 파일에 대한 추가 코드를 작성합니다.

# articles/views.py

def create(request):
    if request.method == 'POST':
        form = ArticleForm(request.POST, request.FILES)
...

이미지 업로드 입력 양식 확인


이미지 업로드 결과 확인


2. 업로드 이미지 제공

2.1 업로드 이미지 제공하기

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

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

<img src="{{ article.image.url }}" alt="img">

업로드 이미지 출력 확인 및 MEDIA_URL 확인


이미지를 업로드하지 않은 게시물은 detail 템플릿을 렌더링 할 수 없습니다. 이미지 데이터가 있는 경우에만 이미지를 출력할 수 있도록 처리해야 합니다.

<!-- articles/detail.html -->

{% if articles.image %}
  <img src="{{ article.image.url }}" alt="img">
{% endif %}

 

2.2 업로드 이미지 수정

수정 페이지 form 요소에 enctype 속성을 추가해 줍니다.

<!-- articles/update.html -->

<h1>UPDATE</h1>
<form action="{% url 'articles:update' article.pk %}" method="POST" enctype="multipart/form-data">
  {% csrf_token %}
  {{ form.as_p }}
  <input type="submit">
</form>

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

# articles/views.py

def update(request, pk):
    article = Article.objects.get(pk=pk)
    if request.method == 'POST':
        form = ArticleForm(request.POST, request.FILES, instance=article)
    ...

참고

1. 'upload_to' argument

ImageField()의 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}/{fielname}'

image = models.ImageField(blank=True, upload_to=articles_image_path)

 

2. request.FILES가 두 번째 위치 인자인 이유

ModelForm 상위 클래스 BaseModelForm의 생성사 함수 키워드 인자입니다.