LoginSignup
2
2

More than 3 years have passed since last update.

django でのファイルアップロード

Posted at

0.0 主な内容

django(本記事ではversino3.1)でのファイルアップロードに関してまとめます。
この記事を読むことで、
 1 テキストのアップロード
 2 画像のアップロード
 3 オーディオのアップロード
の方法について知ることができます。
主にdjangoやプログラミング初心者を対象とした記事ですが、djangoアーキテクチャの全体像について、基本的な内容は既知のものと想定しています。

また、本記事中では、
 1 post_fileディレクトリ下で下記のコマンドにてプロジェクトを開始し、

  $ django-admin startproject post_file . 

 2 その後template、static、mediaディレクトリを作成し、以下のようなディレクトリ構成になっている前提とします。

$ project/(プロジェクトディレクトリ)
  .
  │── config/(設定ディレクトリ)
  │   │── __init__.py
  │   │── settings.py
  │   │── urls.py
  │   │── wsgi.py
  │── post_file_app/(アプリケーションディレクトリ)
  │   │── __initi__.py  
  │   │── admin.py
  │   │── apps.py 
  │   │── migrations
  │   │   │── __init__.py 
  │   │── models.py 
  │   │── test.py
  │   │── views.py
  │── manage.py
  │── template/ 
  │── static/
  │── media/
  │   │──image/ 
  │   │──audio/ 

1.0 ファイルアップロードまでの主な流れ

ファイルアップロードに関しては、
 1 管理者画面から(サイト管理者が)アップロード
 2 ユーザーフォームから(サイト利用者が)アップロード
の二つが考えられますので、以下、場合分けします。

1.1 管理者画面から(サイト管理者が)アップロード 

1.1.1 settings.pyに設定を追記する。

project/config/settings.py
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'post_file_app',#これを追記
    'media',#これを追記
]

BASE_DIR = Path(__file__).resolve(strict=True).parent.parent#これを追記
MEDIA_ROOT = os.path.join(BASE_DIR,'media')#これを追記
MEDIA_URL = '/media/'#これを追記

djangoではアップロードした画像やオーディファイルを直接データベースには格納せずに、事前に用意したファイルに格納し、必要な時はそのパスからファイルを取得します。上記では、MEDIA_ROOTにてその格納するディレクトリを指定しています。

また、MEDIA_URLは、ファイルを表示するときに、/media/ と言うurlを割り当てて表示するという設定です。

1.1.2 model.pyにてアップロードするデータのレイアウトを定義する

project/post_file_app/model.py
class PostFile(models.Model):
    usersname = models.CharField(max_length=50)#テキストアップロード
    image =models.ImageField(upload_to='images/',verbose_name='image',null=True,blank=True)#画像アップロード
    audio = models.FileField(default='', upload_to='audio/')#オーディオアップロード
    def __str__(self):
        return self.usersname

何をアップロードするかによって、CharField、ImageField、FileFieldを使い分ける点に注意します。
以下二つのコマンドでモデルのマイグレーションも忘れずに行います。

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

1.1.3 admin.pyに設定を追記し、管理者画面からアップロードできるようにする

model.pyでPostFileクラスを定義しただけでは、管理者画面からアップロードできません。
以下のようにadmin.pyに追記することで、管理者画面からアップロードができるようになります。

project/post_file_app/admin.py

from .models import PostFile
admin.site.register(PostFile)

1.2 ユーザーフォームから(サイト利用者が)アップロード

この場合、単なる管理者画面上からのアップロードに加えて、新たに
 1 入力フォームを作成(htmlファイル作成、form.py作成)
 2 アップロードするファイルのvalidationの実装(views.pyにてロジックを記載)
が必要になります(ただし、本記事内ではvalidationを自作しないので、コードは少しし書く程度です)。

1.2.1 入力フォームの作成

まずはhtmlファイルを用意します。project/template/ディレクトリに、post.htmlファイルを作成しまし、下記のとおり書きます。 

project/template/post.html
<!doctype html>
<html lang="en">
    <head>
    </head>
    <body >
    <form method="POST" action='' enctype='multipart/form-data'>{% csrf_token %}
   {{ form.username }}
   {{ form.image }}
   {{ form.audio }}
    </body>
</html>

ここでまず、encenctype='multipart/form-data'と言うのは画像やオーディオファイルをアップロードするときにhtmlのformタグ内に記載する必要があります。これを省くと、のちにdjangoは画像、オーディオファイルを取得できません。

また、{% csrf_token %}も呪文のようなもので、ファイルアップロード時に必須となります。

さらに、username、image、audioは、すでに書いたproject/post_file_app/model.pyで記載した変数名(username、image、audio)と一致させる必要があります。

では次にform.pyをpost_file_app内で新たに作成し、以下を追記し入力フォームを作成します。

project/post_file_app/form.py
from django import forms
from .models import PostFile


class PostFileForm(forms.ModelForm):
    def __init__(self,*args,**kwargs):
        super().__init__(*args,**kwargs)
        self.fields['username'].widget.attrs.update({'placeholder':'text'})
        self.fields['image'].widget.attrs.update({'placehodler':'image upload'})
        self.fields['audio'].widget.attrs.update({'placehodler':'audio upload'})
    class Meta:
        model = TestPost
        fields = ('text','image','audio')

最後に作成したフォームを表示するために、views.pyでビューを作成し、urls.pyでビューに対してurlを割り当てます。

project/post_file_app/views.py
from django.shortcuts import render,redirect
from django.views.generic import CreateView
from .forms import PostFileForm

class PostFileView(CreateView):
    def post(self,request,*args,**kwargs):
        form = PostFileForm(request.POST,request.FILES)
        content_dict={
            'form':form
        }
        if not form.is_valid():#ファイルが正しく入力されているかチェック(validation)
            return render(request,'error.html')#error.htmlは、記事中では作成してませんが、各自用意してください。
        form.save()
        return redirect('success_page')
    def get(self,request,*args,**kwargs):
        form = PostFileForm(data=request.GET)
        return render(request,'post.html',{'form':form,})

ここで、formと言う変数が出ていますが、これは既述したpost.htmlのform.username、form.image、form.audioのformと一致させてください。
また、PostFileForm( )の引数として、request.POSTとrequest.FILESとありますが、
前者はdjangoがテキストを、後者は画像やオーディオファイルを取得するために必要なものです。

project/post_file_app/urls.py
from django.urls import path
from .views import Register,LoginView,LogoutView
from mystudio.views import RenderPostedSong
from .views import PostSongView,TestPostView,TestPostView,RenderTestPost

urlpatterns = [
    path('post_file_view/',PostFileView.as_view(),name='post_file_view'),
    path('success/',success,name='success_page',#本記事内ではviewを定義していません
    path('error/',error,name='error_page',#本記事内ではviewを定義していません
]

終わり

以上です。これでdjangoにてテキスト、画像、オーディオファイルのアップロードができるようになりました。

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2