[Django] Static File / Media File

문지은·2023년 4월 26일
0

Django 기초

목록 보기
9/14
post-thumbnail

정적 파일

  • HTML을 제외하고 웹 페이지를 렌더링 할 때 필요한 추가적인 파일을 의미한다.
  • 서버의 데이터들이 어느정도 가공된 후 보여지는 동적파일과 달리, 서버에 미리 저장되어 있어야하며, 서버에 저장된 그대로를 서비스한다.
  • 장고에서 정적파일은 아래의 두가지 파일로 분류될 수 있다.

Static File

  • 응답할 때 별도의 처리 없이 파일 내용을 그대로 보여주면 되는 파일
    • 사용자의 요청에 따라 내용이 바뀌는 것이 아니라 요청한 것을 그대로 보여주는 파일
  • 파일 자체가 고정되어 있고, 서비스 중에도 추가되거나 변경되지 않고 고정되어 있음
    • 예를 들어, 웹사이트는 일반적으로 이미지, 자바 스크립트 또는 CSS와 같은 미리 준비된 추가 파일(움직이지 않는)을 제공해야 함
  • Django에서는 이러한 파일들을 “static file”이라 함
    • Django는 staticfiles 앱을 통해 정적 파일과 관련된 기능을 제공

Media File

  • 미디어 파일
  • 사용자가 웹에서 업로드하는 정적 파일(user-uploaded)
  • 유저가 업로드 한 모든 정적 파일
  • 파일 자체는 고정되어 있지만 언제 어떤 파일이 제공될 지는 예측할 수 없음

⭐ Static files 구성하기

Django에서 정적 파일을 구성하고 사용하기 위한 몇가지 단계

  1. INSTALLED_APPSdjnago.contrib.staticfiles가 포함되어 있는지 확인하기
  2. settings.py 에서 STATIC_URL을 정의하기
# settings.py

INSTALLED_APPS = [
    'articles',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

...

STATIC_URL = '/static/'
STATICFILES_DIRS = [
    BASE_DIR / 'static',
]
  1. 앱의 static 폴더에 정적 파일 위치 하기
    • ex) my_app/static/sample_img.jpg
  2. 템플릿에서 static 템플릿 태그를 사용하여 지정된 경로에 있는 정적 파일의 URL 만들기
{% load static %}

<img src="{% static 'sample.jpg' %}" alt="sample image" height="350">

Django template tag

{% load %}

  • load tag
  • 특정 라이브러리, 패키지에 등록된 모든 템플릿 태그와 필터 로드

{% static '' %}

  • static tag
  • STATIC_ROOT에 저장된 정적 파일에 연결

Static files 관련 Core Settings

STATIC_ROOT

  • Default : None
  • Django 프로젝터에서 사용하는 모든 정적 파일을 한 곳에 모아 넣는 경로
  • collectstatic이 배포를 위해 정적 파일을 수집하는 디렉토리의 절대 경로
  • 개발 과정에서 settings.py의 DEBUG 값이 True로 설정되어 있으면 해당 값은 적용되지 않음
  • 실 서비스 환경(배포 환경)에서 Django의 모든 정적 파일을 다른 웹 서버가 직접 제공하기 위해 사용
  • 배포 환경에서는 Django를 직접 실행하는 것이 아니라, 다른 서버에 의해 실행되기 때문에 실행되는 다른 서버는 Django에 내장되어 있는 정적 파일들을 인식하지 못함 (내장되어 있는 정적 파일들을 밖으로 꺼내는 이유)

[참고] collectstatic

  • STATIC_ROOT에 Django 프로젝트의 모든 정적 파일을 수집
# settings.py

STATIC_ROOT = BASE_DIR / 'staticfiles'
$ python manage.py collectstatic

STATICFILES_DIRS

  • Default : [] (empty list)
  • app/static/ 디렉토리 경로를 사용하는 것(기본 경로) 외에 추가적인 정적 파일 경로 목록을 정의하는 리스트
  • 추가 파일 디렉토리에 대한 전체 경로를 포함하는 문자열 목록으로 작성되어야 함
# 작성 예시

STATICFILES_DIRS = [
    BASE_DIR / 'static',
]

STATIC_URL

  • Default : None
  • STATIC_ROOT에 있는 정적 파일을 참조 할 때 사용할 URL
  • 개발 단계에서는 실제 정적 파일들이 저장되어 있는 app/static/ 경로(기본경로) 및 STATICFILES_DIR에 정의된 추가 경로들을 탐색
  • 실제 파일이나 디렉토리가 아니며, URL로만 존재
  • 비어 있지 않은 값으로 설정한다면 반드시 slash(/)으로 끝나야 함
# 작성 예시

STATIC_URL = '/static/'

⭐ Static files 사용하기

방법 1 - 기본 경로에 있는 static file 가져오기

  1. articles/static/articles 경로에 이미지 파일 배치하기

  2. static tag를 사용해 이미지 파일 출력하기

{% load static %}

<img src="{% static 'articles/sample_img_1.png' %}" alt="sample-image-1">

방법 2 - 추가 경로에 있는 static file 가져오기

  1. 추가 경로 작성
# settings.py

STATICFILES_DIRS = [
    BASE_DIR / 'static',
]
  1. static/ 경로에 이미지 파일 배치하기

  1. static tag를 사용해 이미지 파일 출력하기
{% load static %}

<img src="{% static 'sample_img_2.png' %}" alt="sample-image-2">

STATIC_URL 확인하기

  • Django가 해당 이미지를 클라이언트에게 응답하기 위해 만든 image url 확인하기
    • 개발자 도구 - inspect 버튼을 통해 확인
  • STATIC_URL + static file 경로 로 설정됨

⭐ Media Files

ImageField()

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

FileField()

  • FileField(upload_to=’’, storage=None, max_length=100, **options)
  • 파일 업로드에 사용하는 모델 필드
  • 2개의 선택 인자를 가지고 있음
    1. upload_to
    2. storage

FileField / ImageField 를 사용하기 위한 단계

  1. settings.py에 MEDIA_ROOT, MEDIA_URL 설정
  2. upload_to 속성을 정의하여 업로드된 파일에 사용할 MEDIA_ROOT의 하위 경로를 지정 (선택사항)

MEDIA_ROOT

  • Default : ’’ (Empty string)
  • 사용자가 업로드 한 파일(미디어 파일)들을 보관할 디렉토리의 절대 경로
  • Django는 성능을 위해 업로드한 파일은 데이터베이스에 저장하지 않음
    • 데이터베이스에 저장 되는 것은 파일 경로
  • MEDIA_ROOTSTATIC_ROOT와 반드시 다른 경로로 지정해야 함
# settings.py

# media
MEDIA_ROOT = BASE_DIR / 'media'

MEDIA_URL

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

# media
MEDIA_URL = '/media/'

개발 단계에서 사용자가 업로드한 미디어 파일 제공하기

  • 사용자로부터 업로드 된 파일이 프로젝트에 업로드 되고나서, 실제로 사용자에게 제공하기 위해서는 업로드된 파일의 URL 필요
    • 업로드 된 파일의 URL == settings.MEDIA_URL
    • 위 URL을 통해 참조하는 파일의 실제 위치 == settings.MEDIA_ROOT
# crud/urls.py

from django.contrib import admin
from django.urls import path, include
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)

⭐ Media File 사용하기

CREATE

ImageField 작성

  • 기존 컬럼 사이에 작성해도 실제 테이블에 추가 될 때는 가장 우측(뒤)에 추가됨
# articles/models.py

from django.db import models

# Create your models here.
class Article(models.Model):
    title = models.CharField(max_length=30)
    content = models.TextField()
    # ImageField 작성
    image = models.ImageField(blank=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

Model field option (1) - blank

  • Defalut : False
  • True인 경우 필드를 비워 둘 수 있음
    • 이럴 경우 DB에는 ‘’(빈 문자열) 저장
  • 유효성 검사에서 사용 됨(is_valid)
    • “Validation-related”
    • 필드에 blank=True 가 있으면 form 유효성 검사에서 빈 값을 입력받을 수 있음

Model field option (2) - null

  • Defalut : False
  • True 인 경우 Django는 빈 값을 DB에 NULL로 저장함
    • “Database-related”
  • 주의사항 : ChartField, TextField와 같은 문자열 기빈 필드에는 null 옵션 사용을 피해야 함
    • 문자열 기반 필드에 null=True로 설정 시 데이터 없음에 대한 표현에 “빈 문자열”과 “NULL” 2가지 모두 가능하게 됨
    • “데이터 없음”에 대한 표현에 두 개의 가능한 값을 갖는 것은 좋지 않음
    • Django는 문자열 기반 필드에서 NULL이 아닌 빈 문자열을 사용하는 것이 규칙

Migrations

  • ImageField를 사용하려면 반드시 Pillow 라이브러리가 필요
    • Pillow 설치 없이는 makemigrations 실행 불가
$ pip install pillow
    
$ python manage.py makemigrations
$ python manage.py migrate
    
$ pip freeze > requirements.txt
  • Pillow
    • 광범위한 파일 형식 지원, 효율적이고 강력한 이미지 처리 기능을 제공하는 라이브러리
    • 이미지 처리 도구를 위한 견고한 기반 제공

enctype 속성 변경

  • 파일 또는 이미지 업로드 시에는 form 태그에 enctype 속성을 다음과 같이 변경해야 함.
<!-- article/create.hmtl -->

{% extends 'base.html' %}

{% block content %}
  <h1>글작성</h1>
  <hr>

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

{% endblock content %}

request.FILES

  • 파일 및 이미지는 request의 POST 속성 값으로 넘어가지 않고 FILES 속성 값에 담겨 넘어감
# articles/views.py

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

이미지 첨부하기

  • 이미지를 첨부하지 않으면 blank=True 속성으로 인해 빈 문자열 저장
  • 이미지를 첨부한 경우는 MEDIA_ROOT 경로에 이미지가 업로드 됨
  • 파일 자체가 아닌 경로가 저장된다는 것 잊지 말 것!!!
  • 만약 같은 이름의 파일을 업로드 한다면 Django는 파일 이름 끝에 임의의 난수 값을 붙여 저장함.

READ

업로드 이미지 출력하기

  • 업로드 된 파일의 상대 URL은 Django가 제공하는 url 속성을 통해 얻을 수 있음
    • article.image.url - 업로드 파일의 경로
    • article.image - 업로드 파일의 파일 이름
<!-- article/detail.hmtl -->

<img src="{{article.image.url}}">
  • 이미지를 업로드 하지 않은 게시물을 detail 템플릿을 출력할 수 없는 문제 해결
    • 이미지 데이터가 있는 경우에만 이미지 출력할 수 있도록 처리
<!-- article/detail.hmtl -->

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

UPDATE

업로드 이미지 수정하기

  • enctype 속성 값 추가
<!-- article/update.hmtl -->

{% extends 'base.html' %}

{% block content %}
  <h1>글수정</h1>
  <hr>

  <form action="{% url 'articles:update' article.pk %}" enctype="multipart/form-data" method="POST">
...
  • 이미지 파일이 담겨 있는 request.FILES 추가 작성
# 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)
profile
코드로 꿈을 펼치는 개발자의 이야기, 노력과 열정이 가득한 곳 🌈

1개의 댓글

comment-user-thumbnail
2024년 8월 29일

penalty shooters 2 is an online soccer game where you play as both the goalie and the penalty taker. To score goals and prevent the opposing side from scoring as well is the aim of the game. It offers a tournament mode where you may choose your team from various leagues and countries.

답글 달기