Help us understand the problem. What is going on with this article?

Djangoでファイルアップローダを作る

More than 1 year has passed since last update.

古い情報及び醜いコードがあるので更新しました。(2017/03/16)

環境

  • Python 3.5.1
  • Django 1.9.1
  • Virtualenv 15.0.1
  • OS X El Capitan 10.11.6

最終構成

file_uploader
    ├── db.sqlite3
    ├── file_uploader
    │   ├── __init__.py
    │   ├── settings.py
    │   ├── urls.py
    │   └── wsgi.py
    ├── manage.py
    ├── requirements.txt
    └── upload_form
        ├── __init__.py
        ├── admin.py
        ├── apps.py
        ├── migrations
        │   ├── 0001_initial.py
        │   └── __init__.py
        ├── models.py
        ├── static
        │   └── files
        │       └── __init__.py
        ├── templates
        │   └── upload_form
        │       ├── base.html
        │       ├── complete.html
        │       └── form.html
        ├── tests.py
        ├── urls.py
        └── views.py

こんな感じの構成になっていればいいかなって思います。
__pycache__ は省略

セットアップ

プロジェクト作成

$ pip install Django==1.9.1
$ django-admin.py startproject file_uploader
$ cd file_uploader
$ django-admin.py startapp upload_form
# あとでどのファイルがいつアップロードされたか確認したいので
$ python manage.py createsuperuser

settings.py を変更

settings.py
INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'upload_form', # 追加
)

・・・

LANGUAGE_CODE = 'ja'

TIME_ZONE = 'Asia/Tokyo'

・・・

ぐらいしておけばいいかな

とりあえず確認

$ python manage.py migrate
$ python manage.py runserver

http://127.0.0.1:8000

にアクセスして例のアレが出てきたらOK

upload_form Appの構築

models.py

upload_form/models.py
from django.db import models
from datetime import datetime

class FileNameModel(models.Model):
    file_name = models.CharField(max_length = 50)
    upload_time = models.DateTimeField(default = datetime.now)

file_name : ファイル名
upload_time : アップロード日時(デフォルトで現在日時が入る)

views.py

upload_form/views.py
from django.shortcuts import render, redirect
from django.template.context_processors import csrf
from django.conf import settings
from upload_form.models import FileNameModel
import sys, os
UPLOADE_DIR = os.path.dirname(os.path.abspath(__file__)) + '/static/files/'

def form(request):
    if request.method != 'POST':
        return render(request, 'upload_form/form.html')

    file = request.FILES['file']
    path = os.path.join(UPLOADE_DIR, file.name)
    destination = open(path, 'wb')

    for chunk in file.chunks():
        destination.write(chunk)

    insert_data = FileNameModel(file_name = file.name)
    insert_data.save()

    return redirect('upload_form:complete')

def complete(request):
    return render(request, 'upload_form/complete.html')

テンプレート

upload_form/templates/upload_form/base.html
<!DOCTYPE html>
<html lang="ja">
    <head>
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta name="viewport" content="content">
        <title>ファイルアップローダ</title>
    </head>
    <body>
        {% block content %}
            {{ content }}
        {% endblock %}
    </body>
</html>
upload_form/templates/upload_form/form.html
{% extends "upload_form/base.html" %}

{% block title %}アップローダサンプル{% endblock title %}
{% block content %}
    <form method="POST" enctype="multipart/form-data">
        {% csrf_token %}
        <input type="file" name="file">
        <input type="submit" value="アップロード">
    </form>
{% endblock content %}
upload_form/templates/upload_form/complete.html
{% extends "upload_form/base.html" %}

{% block title %}アップロード完了{% endblock title %}
{% block content %}
    <div align="center">
        <h1 align="center">アップロード完了</h1>
        <a href="{% url 'upload_form:form' %}"><button>戻る</button></a>
    </div>
{% endblock content %}

アップロードするともしかするとアップロード先のディレクトリがないぞ!って怒られるかもしれないので
upload_form/static/files/ というような構成でディレクトリを作成しておいてください。

URL設定

urls.py

upload_form/urls.py を新規作成して以下

upload_form/urls.py
from django.conf.urls import url
from upload_form import views

urlpatterns = [
    url(r'^$', views.form, name = 'form'),
    url(r'^complete/', views.complete, name = 'complete'),
]
file_uploader/urls.py
from django.conf.urls import url, include
from django.contrib import admin

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

Django管理サイト設定

admin.py

upload_form/admin.py
from django.contrib import admin
from upload_form.models import FileNameModel

class FileNameAdmin(admin.ModelAdmin):
    list_display = ('id', 'file_name', 'upload_time')
    list_display_links = ('id', 'file_name')

admin.site.register(FileNameModel, FileNameAdmin)

Django管理サイトからデータを閲覧・編集できるようにする

マイグレーション & 起動

$ python manage.py makemigrations
$ python manage.py migrate
$ python manage.py runserver

http://127.0.0.1:8000
にアクセスしたらクソショボいWebページが表示されると思われる。
そこから適当にアップロードしてあげると上手くいく。

スクリーンショット 2016-08-18 午後3.42.39.png

http://127.0.0.1:8000/admin/
にアクセスしてログインして
http://127.0.0.1:8000/admin/upload_form/filenamemodel/
に入ったらデータがあることを確認する!!

スクリーンショット 2016-08-18 午後3.43.48.png

アップロードしたファイルが何故かiOSのCertificateやらp12ファイルばかりで申し訳ないかぎりだが確認ができた!

あとは焼くなり煮るなり。

私は、去年の卒研でCSVファイルをアップロードすると中身を読み取ってDBテーブルにインサートするような処理をしました。

リポジトリ

https://github.com/nnsnodnb/django-file-uploader

一応リポジトリリンク

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away