[Django] Image

Jin·2021년 9월 13일
2

django

목록 보기
8/14
post-thumbnail
post-custom-banner

Media File

  • 사용자가 웹에서 업로드하는 정적 파일

1. FileField

  • 파일 업로드에 사용하는 모델 필드
  • 2개의 선택 인자를 가지고 있다.
    • upload_to
    • storage

1) MEDIA_ROOT

  • 사용자가 업로드 한 파일(미디어 파일)들을 보관할 디렉토리의 절대 경로
  • django는 성능을 위해 업로드 파일은 db에 저장하지 않음
    • 실제 db에 저장되는것은 파일의 경로
  • MEDIA_ROOT는 STATIC_ROOT와 반드시 다른 경로로 지정해야 함
# settings.py

MEDIA_ROOT = BASE_DIR / 'media'

# 유저가 업로드하면 자동으로 폴더가 생성 됨

2) MEDIA_URL

  • MEDIA_ROOT에서 제공되는 미디어를 처리하는 URL
  • 업로드 된 파일의 주소(URL)을 만들어주는 역할
    • 웹 서버 사용자가 사용하는 public URL
  • 비어 있지 않은 값으로 설정 한다면 반드시 /로 끝나야함
  • MEDIA_URL는 STATIC_URL와 반드시 다른 경로로 지정해야 함
# settings.py

MEDIA_URL = '/media/'


# app/urls.py

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

urlpatterns=[
	
] + static(settings.MEDIA_URL, document_root = settings.MEDIA_ROOT)
# 업로드 된 URL,				실제 파일의 위치

# 사용자가 업로드 한 파일이 우리 프로젝트에 업로드 되지만, 실제로 사용자에게 제공하기 위해서는 업로드 된 파일의 URL이 필요

3) upload_to

  • 업로드 디렉토리와 파일 이름을 설정하는 2가지 방법을 제공
    • 문자열 값이나 경로 지정
    • 함수 호출
  1. 문자열 경로 지정 방식
    : 파이썬의 strftime() 형식이 포함될 수 있으며, 이는 파일 업로드 날짜/시간으로 대체
# models.py

class MyModel(models.Model):
    # MEDIA_ROOT/uploads/ 경로로 파일 업로드
    upload = models.FileField(upload_to = 'uploads/')
    # or
    # MEDIA_ROOT/uploads/2021/01/01 경로로 파일 업로드
    upload = models.FileField(upload_to = 'uploads/%Y/%m/%d/')

2. ImageField

  • 이미지 업로드에 사용하는 모델 필드
  • FileField를 상속받는 서브 클래스이기에 FileField의 모든 속성 및 메서드가 사용가능하며 사용자에 의해 업로드 된 객체가 유효한 이미지인지 검사함.
  • ImageField 인스턴스는 최대 길이가 100자인 문자열로 DB에 생성되며, max_length 인자를 사용하여 최대 길이를 변경 할 수 있음.
  • 사용하려면 반드시 Pillow 라이브러리가필요

위의 MEDIA_ROOT, MEDIA_URL이 이미지 업로드의 준비 단계.

DB에 저장되는 것은 파일의 경로

1) Image Upload(CREATE) 문자열 방식

  • 업로드 한 파일은 request.FILES 객체로 전달됨
  • upload_to ='images/' : 실제 이미지가 저장되는 경로를 지정
  • blank = True (Validation-related)
    • 이미지 필드에 빈 값(빈 문자열)이 허용되도록 설정(이미지를 선택적으로 업로드 할 수 있도록)
    • Model field option
    • 기본 값: False
    • 유효성 검사에서 사용됨
      • 필드에 blank=True가 있으면 form 유효성 검사에서 빈 값을 입력 가능
  • null (Python에서 None과 비슷, Database-related)
    • Model field option
    • 기본 값: False
    • CharField, TextField와 같은 문자열 기반 필드에는 사용하는 것을 피해야 함
    • 문자열 기반 필드에 True로 설정시 '데이터 없음(no data)'에 '빈 문자열(1)'과 'NULL(2)'의 2가지 가능한 값이 있음을 의미
    • 대부분 경우 '데이터 없음'에 대해 두 개의 가능한 값을 갖는것은 중복 되며, Django는 NULL이 아닌 빈 문자열을 사용하는 것이 규칙
  • 문자열 기반 및 비문자열 기반 필드 모두에 대해 null option은 DB에만 영향을 미치므로, form에서 빈 값을 허용하려면 blank=True를 설정해야함
# models.py

class MyModel(models.Model):
    image = models.ImageField(blank= True, upload_to = 'images/'
    
# app_name/create.html
<form action='{% url 'articles:create' %}' method="POST" enctype='multipart/form-data'>

#. views.py
def create(request):
   if request.method == 'POST':
   	form = ArticleForm(request.POST, request.FILES)
        if form.is_valid():
        	article = form.save()
            	rerdirect('articles/detail.html', article.pk)

form 요소 - enctype(인코딩)속성

  1. multipart/form-data
  • 파일/이미지 업로드 시에 반드시 사용해야 함(전송되는 데이터의 형식을 지정)
  • <input type='file'> 을 사용할 경우에 사용

form 요소 - accept 속성

  • 입력 허용할 파일 유형을 나타내는 문자열
  • 쉼표로 구분된 '고유 파일 유형 지정자'
  • 파일 검증 X
    (이미지만 accpet 해도 비디오나 오디오 파일 제출 가능)

2) Image Upload (함수 호출 방식)

반드시 2개의 인자(instance, filename)을 사용 함

  • instance
    • FileField가 정의된 모델의 인스턴스
    • 대부분 이 객체는 아직 DB에 저장되지 않았으므로 PK 값이 아직 없을 수 있음
  • file name
    • 기존 파일에 제공된 파일 이름
# models.py

def articles_image_path(instance, filename):
	# MEDEIA_ROOT/user_<pk>/ 경로로 <filename> 이름으로 업로드
    return f'user_{instance.pk}/{filename}'

class Article(models.Model):
	image = models.ImageField(upload_to = articles_image_path)

3) Image Upload(READ)

  • 업로드 된 파일의 경로는 django가 제공하는 'url' 속성을 통해 얻을 수 있음
  • static, media 결국 모두 서버에 요청해서 조회하는 것
  • 서버에 요청하기 위한 url을 urls.py가 아닌 settings에 먼저 작성 후 urlpatterns에 추가하는 형식
<img src="{{ article.image.url }}" alt="{{ article.image }}">
	# 업로드 파일의 경로		#업로드 파일의 파일 이름

4) Image Update (Update)

  • 이미지는 바이너리 데이터(하나의 덩어리)이기 때문에 텍스트처럼 일부만 수정 하는것 불가능
  • 새로운 사진으로 덮어 씌우는 방식을 사용
  • image가 없는 게시글의 경우 출력할 이미지가 없기 때문에 if를 사용하여 이미지가 있을때만 표시하거나 없을때 출력한 static 이미지를 설정해주면 됨
# views.py

def update(request, pk):
	article = get_object_or_404(Article, pk=pk)
    if request.method == "POST":
    	form = ArticleForm(request.POST, request.FILES, instance=article) # 마지막 위치에 넣을꺼면 files=request.FILES라고 해야 함
        if form.is_valid():
            form.save()
            return redirect('articles:detail', article.pk)

위의 ArticleForm뒤의 매개변수 순서가 저렇게 된 이유는 아래 링크 참고
https://github.com/django/django/blob/main/django/forms/models.py#L286 위치인자, 키워드 인자 규칙 때문에

5) Image Resizing

  • 실제 원본 이미지를 서버에 그대로 업로드 하는 것은 서버의 부담이 큰 작업
  • <img> 태그에서 직접 사이즈를 조정할 수도 있지만, 업로드 될 때 이미지 자체를 resizing에서 업로드 (원본말고)
  • django-imagekit 라이브러리 활용

참고 : https://github.com/matthewwithanm/django-imagekit

profile
내가 다시 볼려고 작성하는 블로그
post-custom-banner

1개의 댓글

comment-user-thumbnail
2022년 1월 23일

좋아요!

답글 달기