Django
파일이 저장될 디렉토리와, 그 디렉토리를 가리킬 URL 설정
settings.py
import os
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
urls.py
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
...
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
Pillow 설치
pip install pillow
pillow를 설치 하지 않으면 아래 모델 생성에서 ImageField를 사용하지 못하는 에러가 발생
model 생성
from django.db import models
class Home(models.Model):
title = models.CharField(max_length=30)
banner = models.ImageField(null=True)
# banner = models.ImageField(upload_to='images', null=True)
upload_to 옵션을 넣어서, MEDIA_ROOT 안에 추가적인 디렉토리에 저장할 수 있습니다.
migrate
python manage.py makemigrations && python manage.py migrate
Frontend에서 파일 보내기
1) HTML만 이용
<body>
<h1>Home</h1>
<form method="POST" enctype="multipart/form-data" action="/">
{% csrf_token %}
<input type="file" name="banner">
<input type="text" name="title">
<button>submit</button>
</form>
</body>
2) Ajax 이용
static 디렉토리 설정, csrftoken 설정은 생략하고 설명하겠습니다.
{% load static %}
<head>
<script src="{% static 'js/image.js' %}"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.3/jquery.min.js" integrity="sha512-STof4xm1wgkfm7heWqFJVn58Hm3EtS31XFaagaa8VMReCXAkQnJZ+jEy8PCC/iT18dFy95WcExNHFTqLyp72eQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
</head>
<body>
<h1>Home</h1>
<input type="file" name="banner">
<input type="text" name="title">
<button onclick="sendData()">submit</button>
</body>
javascript file을 사용할 것이므로 {% load static %}
사용할 javascript file 호출 (static/js/image.js)
그 아래에는 ajax를 사용하기 위해 jquery 호출
ajax를 통해서 보낼것이므로 form은 지우고 진행해 보겠습니다.
(form태그가 없어야 하는게 아니라 없이도 가능한걸 보기 위해서 입니다.)
static/js/image.js
function sendData(){
let formData = new FormData();
let banner = document.querySelector('[name="banner"]').files[0];
let title = document.querySelector('[name="title"]').value;
formData.append("banner", banner);
formData.append('title', title);
$.ajax({
url: '/',
method: 'POST',
processData: false,
contentType: false,
enctype: 'multipart/form-data',
data: formData,
success: function (data) {
window.location.reload();
},
});
}
파일에 대한 접근:
type='file'인 input에 파일이 담기면, 하나만 담았어도 files라는 Array에 담기기 때문에 files[0] 으로 접근합니다.
FormData에 data 담기:
javascript로 이미지 파일을 보내기 위해서는 FormData()를 이용해서 이 안에 파일을 담아서 보내야 합니다.
ajax 에서는 아래와 같은 설정을 해야하는 것이 일반적으로 ajax를 보낼때와 다른 차이점입니다.
processData: false,
contentType: false,
enctype: 'multipart/form-data',
Backend에서 파일 받기
from django.shortcuts import render
from home.models import Home
def home(request):
banner_image = request.FILES.get('banner')
Home.objects.create(banner=banner_image)
return render(request, 'home.html')
* 이미지 파일 이름을 변경하면서 저장
backend에서 이미지 파일을 변경
from django.shortcuts import render
from home.models import Home
def home(request):
banner_image = request.FILES.get('banner')
ext = str(banner_image).split(".")[-1]
image_name = f'new_name.{ext}'
home = Home.objects.create(title='test')
home.banner = banner_image
home.banner.name = image_name
home.save()
return render(request, 'home.html')
* 주의사항
아래와 같이 ImageField도 함께 생성하면서 바로 name을 변경하는 것은 적용이 안됩니다.
위와 같이 ORM Query로 ImageField 없이 row를 생성하고, 그 이후에 ImageField에 파일을 넣고 이름을 변경해야 합니다.
from django.shortcuts import render
from home.models import Home
def home(request):
banner_image = request.FILES.get('banner')
ext = str(banner_image).split(".")[-1]
image_name = f'new_name.{ext}'
home = Home.objects.create(title='test', banner=banner_image)
home.banner.name = image_name
home.save()
return render(request, 'home.html')
* 이미지가 업로드될 디렉토리를 커스텀하기
from django.db import models
from datetime import datetime
def custom_upload_to():
return datetime.now()
class Home(models.Model):
title = models.CharField(max_length=30)
banner = models.ImageField(upload_to=custom_upload_to(), null=True)
위와 같은 식으로 upload_to를 정해두면, 해당하는 조건대로(위에서는 row가 생성되는 시기) MEDIA_ROOT로 설정한 기본 디렉토리 안에서 추가로 디렉토리가 정해집니다.
위와 같이 upload_to를 설정해서 저장할 경우, 파일이름을 변경하면서 동시에 create 가능!!!!!!!
'Python > Django' 카테고리의 다른 글
Django ORM Query: ForeignKey로 연결된 필드 filter (0) | 2023.02.04 |
---|---|
Django Template, render_to_string # backend에서 data 받기 #render_to_string #loader (0) | 2023.01.29 |
Django Template filter: {% with %} (0) | 2023.01.25 |
STATIC_ROOT vs STATICFILES_DIRS (0) | 2023.01.24 |
Django: Database data dump # json으로 데이터 백업, 복구 (0) | 2023.01.17 |