본문 바로가기
Python/Django

[Django] File upload (FileField, ImageField)

by 혀나Lee 2016. 10. 19.

Django 에서 파일(이미지)를 업로드하기 위해서는 FileField 또는 ImageField 를 사용하면 된다.

Django Test Project 만들기

테스트를 위해 간단한 프로젝트를 만든다. (Pycharm 을 사용한다면 더 쉽게 프로젝트를 만들 수 있다.)

$ django-admin.py startproject firstsite

주로 Django project 에서는 startapp 명령어를 통해 app 을 만든다음 application 단위로 코딩을 하지만 본 가이드에서는 Django Project 를 만드는게 목적이 아니므로 app 을 따로 만들지 않고 project 에서 바로 테스트를 할 것이다. (db 또한 Django 에서 제공하는 sqlite3 을 사용할 것이다.)

settings.py 작성하기

MEDIA_ROOT = '/home/attachement'
MEDIA_URL = '/media/'

# 파일업로드 사이즈의 최대값을 설정해주세요. 기본값은 2.5MB입니다.
FILE_UPLOAD_MAX_MEMORY_SIZE = '2621440'
  • MEDIA_ROOT: 실제 파일이 저자될 경로입니다. 해당 경로를 생성하셔야 합니다.
  • MEDIA_URL: 웹 URL을 통해 첨부파일에 접근할 수 있는 URL 경로입니다.

common.py 작성하기

import datetime
import os
import uuid

def file_upload_path(instance, filename):
    ext = filename.split('.')[-1]
    d = datetime.datetiem.now()
    filepath = d.strftime("%Y/%m/%d")
    suffix = d.strftime("%Y%m%d%H%M%S")
    filename = "%s_%s.%s" % (uuid.uuid4().hex, suffix, ext)
    return os.path.join(filepath, filename)
  • common.py 는 제가 임시로 만든 파일로 공통 함수를 작성하기 위해 만든 파일입니다.
  • file_upload_path() 함수는 파일이 업로드 될 때 파일을 올린 날짜별로 폴더로 나누어 구성하려고 만든 함수입니다.

models.py 작성하기

from django.db import models

class FileTest(models.Model):
    id = models.AutoField(primary_key=True)
    path = models.FileField(upload_to=file_upload_path, null=True)

파일을 올리기 위해서는 FileField 또는 ImageField 를 사용해야 하며 upload_to 는 파일을 올릴기 위한 경로를 표현해 주는 것입니다.

여기서 헷갈리지 말아야 하는게 settings.py 에 작성했던 MEDIA_ROOT 는 파일 경로가 시작되는 것을 말하며 파일이 최종으로 올라가는 위치는 upload_to 에 작성된 위치입니다.

즉, 최종 경로는 '/home/attachment/2016/10/18/' 의 경로에 파일이 올라가는 것입니다.

serializers.py 작성하기

from rest_framework import serializers
from .models import FileTest

class FileTestSerializer(serializers.ModelSerializer):
    path = serializes.FileField(required=False)

    class Meta:
        model = FileTest
        fields = '__all__'
        read_only_fields = ('id', )

views.py 작성하기

from rest_framework.viewsets import ModelViewSet
from .models import FileTest
from .serializers import FileTestSerializer

class FileTestViewSet(ModelViewSet):
    queryset = FileTest.objects.all()
    serializer_class = FileTestSerializer

    def create(self, request, *args, **kwargs):
        return super(FileTestViewSet, self).create(request, *args, **kwargs)

urls.py 작성하기

from django.conf.urls import include, url
from django.contrib import admin
from rest_framework.routers import DefaultRouter
from .views import FileTestViewSet

router = DefaultRouter()
router.register(r'file', FileTestViewSet)

urlpatterns = [
    url(r'^admin/', include(admin.site.urls)), 
    url(r'^', include(router.urls)),
]

admin 사이트를 사용하지 않으실 거라면 url 을 추가하지 않으셔도 됩니다.

sqlite3 에 table migrate 하기

$ ./manage.py migrations firstsite
$ ./manage.py migrate

File Upload 테스트하기

파일 업로드 테스트는 Chrome app 인 postman 을 사용한다.

파일 업로드 확인

경로에서 확인

$ cd /home/attachment
$ cd 2016/10/19
$ ls
a596b9ac49ba43419187ae3cb605fb4e_20161019010704.jpg

자신이 설정한 경로로 가서 보면 파일이 업로드된 것을 볼 수 있다.

sqlite3 에서 확인

$ sqlite3 db.sqlite3
sqlite> select * from firstsite_filetest
2|2016/10/19/a596b9ac49ba43419187ae3cb605fb4e_20161019010704.jpg

API 응답 결과로 확인

API 응답 결과로 온 path 로 접속하면 /media/ 경로를 설정해 주지 않았기 때문에 404 에러가 발생한다.

/media 경로 설정하기

Django project 에서 설정하기

Django project 의 urls.py 에 설정하여 static 파일에 접근 가능하도록 만들 수 있다. (하지만, Django 프로젝트는 애플리케이션을 만드는데 최적화 되어있는 프로임워크이다. 따라서 경로를 설정하는 기능은 Django project 를 사용하는 것보다는 nginx 에서 설정하는 것이 바람직하다.)

from django.conf.urls import include, url
from django.contrib import admin
from django.conf.urls.static import static    # 추가
from django.conf import settings                # 추가
from rest_framework.routers import DefaultRouter
from .views import FileTestViewSet

router = DefaultRouter()
router.register(r'file', FileTestViewSet)

urlpatterns = [
    url(r'^admin/', include(admin.site.urls)), 
    url(r'^', include(router.urls)),
]+static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)    # 추가

nginx 에서 설정하기

firstsite 프로젝트의 nginx 파일을 연다. (나는 /etc/nginx/sites-available/ 경로에 파일이 있다.)

$ cd /etc/nginx/sites-available
$ sudo vi firstsite
server {
    listen 8080;
    server_name IP_주소;

    location = /favicon.ico { access_log off; log_not_found off; }
    location /static/ {
        root /home/parallels/firstsite;
    }

    location / {
         include uwsgi_params;
         uwsgi_pass unix:/home/parallels/firstsite/firstsite.sock;
    }

    # 추가
    location /media {
        alias /home/attachment;
    }
}

locaion /media 에 alias 를 MEDIA_ROOT 에 설정했던 경로와 동일하게 설정해 주면 된다.

nginx 서비스를 테스트 해본 후, 성공이 되면 서비스를 다시 실행시켜 준다.

$ sudo service nginx configtest
$ sudo service nginx restart

'Python > Django' 카테고리의 다른 글

[Django] django-crontab  (0) 2016.10.28
[Django] values() values_list() flat  (0) 2016.10.26
[Django] uwsgi + nginx in ubuntu  (0) 2016.10.18
[Django] Test  (0) 2016.10.12
[Django] Extra  (0) 2016.10.06

댓글