Djangoでファイルをアップロードする方法は?[閉まっている]


668

Djangoの初心者として、Django 1.3でアップロードアプリを作成するのに苦労しています。最新のサンプル/スニペットが見つかりませんでした。誰かが最小限ではあるが完全な(モデル、ビュー、テンプレート)サンプルコードを投稿することはできますか?

回答:


1273

ふう、Djangoのドキュメントには、これについての良い例はありません。これがどのように機能するかを理解するために、2時間以上かけてすべての部分を掘り下げました。その知識を得て、ファイルをアップロードしてリストとして表示できるようにするプロジェクトを実装しました。プロジェクトのソースをダウンロードするには、https//github.com/axelpale/minimal-django-file-upload-exampleにアクセスするか、クローンを作成します。

> git clone https://github.com/axelpale/minimal-django-file-upload-example.git

2013-01-30更新: GitHubのソースには、1.3に加えてDjango 1.4の実装もあります。変更点はほとんどありませんが、次のチュートリアルは1.4にも役立ちます。

2013-05-10の更新: GitHubでのDjango 1.5の実装。urls.pyでのリダイレクトの小さな変更と、list.htmlでのurlテンプレートタグの使用法。努力してくれたhubert3に感謝します。

2013-12-07の更新: GitHubでDjango 1.6がサポートされました。myapp / urls.pyで1つのインポートが変更されました。アルテジアンに感謝します

2015-03-17更新:aronysidoroのおかげで、GitHubでDjango 1.7がサポートされました

2015-09-04の更新:nerogitのおかげで、GitHubでDjango 1.8がサポートされています。

アップデート2016-07-03:daavvenerogitのおかげで、GitHubでDjango 1.9がサポートされました

プロジェクトツリー

単一のアプリとアップロード用のmedia /ディレクトリを持つ基本的なDjango 1.3プロジェクト。

minimal-django-file-upload-example/
    src/
        myproject/
            database/
                sqlite.db
            media/
            myapp/
                templates/
                    myapp/
                        list.html
                forms.py
                models.py
                urls.py
                views.py
            __init__.py
            manage.py
            settings.py
            urls.py

1.設定:myproject / settings.py

ファイルをアップロードして提供するには、Djangoがアップロードしたファイルを格納する場所と、Djangoがそれらを提供するURLを指定する必要があります。MEDIA_ROOTとMEDIA_URLはデフォルトでsettings.pyにありますが、空です。詳細については、Djangoファイルの管理の最初の行を参照してください。データベースを設定してmyappをINSTALLED_APPSに追加することも忘れないでください

...
import os

BASE_DIR = os.path.dirname(os.path.dirname(__file__))
...
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'database.sqlite3'),
        'USER': '',
        'PASSWORD': '',
        'HOST': '',
        'PORT': '',
    }
}
...
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
...
INSTALLED_APPS = (
    ...
    'myapp',
)

2.モデル:myproject / myapp / models.py

次に、FileFieldを含むモデルが必要です。この特定のフィールドは、現在の日付とMEDIA_ROOTに基づいて、ファイルをmedia / documents / 2011/12/24 /などに格納します。参照してくださいFileFieldに参照を

# -*- coding: utf-8 -*-
from django.db import models

class Document(models.Model):
    docfile = models.FileField(upload_to='documents/%Y/%m/%d')

3.フォーム:myproject / myapp / forms.py

アップロードを適切に処理するには、フォームが必要です。このフォームにはフィールドが1つしかありませんが、それで十分です。詳細については、Form FileFieldリファレンス参照してください。

# -*- coding: utf-8 -*-
from django import forms

class DocumentForm(forms.Form):
    docfile = forms.FileField(
        label='Select a file',
        help_text='max. 42 megabytes'
    )

4.表示:myproject / myapp / views.py

すべての魔法が発生するビュー。request.FILES取り扱いにご注意ください。私にとっては、request.FILES['docfile']models.FileFieldに保存できるという事実を見つけるのは本当に困難でした。モデルのsave()は、ファイルのファイルシステムへの保存を自動的に処理します。

# -*- coding: utf-8 -*-
from django.shortcuts import render_to_response
from django.template import RequestContext
from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse

from myproject.myapp.models import Document
from myproject.myapp.forms import DocumentForm

def list(request):
    # Handle file upload
    if request.method == 'POST':
        form = DocumentForm(request.POST, request.FILES)
        if form.is_valid():
            newdoc = Document(docfile = request.FILES['docfile'])
            newdoc.save()

            # Redirect to the document list after POST
            return HttpResponseRedirect(reverse('myapp.views.list'))
    else:
        form = DocumentForm() # A empty, unbound form

    # Load documents for the list page
    documents = Document.objects.all()

    # Render list page with the documents and the form
    return render_to_response(
        'myapp/list.html',
        {'documents': documents, 'form': form},
        context_instance=RequestContext(request)
    )

5.プロジェクトのURL:myproject / urls.py

DjangoはデフォルトではMEDIA_ROOTを提供しません。本番環境では危険です。しかし、開発段階では短縮できます。最後の行に注意してください。この行により、DjangoはMEDIA_URLからファイルを提供できるようになります。これは開発段階でのみ機能します。

詳細については、django.conf.urls.static.staticリファレンス参照してください。メディアファイルの配信に関するこの説明もご覧ください。

# -*- coding: utf-8 -*-
from django.conf.urls import patterns, include, url
from django.conf import settings
from django.conf.urls.static import static

urlpatterns = patterns('',
    (r'^', include('myapp.urls')),
) + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

6.アプリのURL:myproject / myapp / urls.py

ビューにアクセスできるようにするには、ビューのURLを指定する必要があります。ここで特別なことはありません。

# -*- coding: utf-8 -*-
from django.conf.urls import patterns, url

urlpatterns = patterns('myapp.views',
    url(r'^list/$', 'list', name='list'),
)

7.テンプレート:myproject / myapp / templates / myapp / list.html

最後の部分:リストのテンプレートとその下のアップロードフォーム。Djangoへのアップロードを可能にするには、フォームのenctype-attributeを「multipart / form-data」に設定し、メソッドを「post」に設定する必要があります。詳細については、ファイルのアップロードのドキュメントをご覧ください。

FileFieldには、テンプレートで使用できる多くの属性があります。たとえば、{{document.docfile.url}}と{{document.docfile.name}}はテンプレートと同じです。これらの詳細については、モデルでのファイルの使用に関する記事ファイルオブジェクトのドキュメントをご覧ください。

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>Minimal Django File Upload Example</title>   
    </head>
    <body>
    <!-- List of uploaded documents -->
    {% if documents %}
        <ul>
        {% for document in documents %}
            <li><a href="{{ document.docfile.url }}">{{ document.docfile.name }}</a></li>
        {% endfor %}
        </ul>
    {% else %}
        <p>No documents.</p>
    {% endif %}

        <!-- Upload form. Note enctype attribute! -->
        <form action="{% url 'list' %}" method="post" enctype="multipart/form-data">
            {% csrf_token %}
            <p>{{ form.non_field_errors }}</p>
            <p>{{ form.docfile.label_tag }} {{ form.docfile.help_text }}</p>
            <p>
                {{ form.docfile.errors }}
                {{ form.docfile }}
            </p>
            <p><input type="submit" value="Upload" /></p>
        </form>
    </body>
</html> 

8.初期化

syncdbとrunserverを実行するだけです。

> cd myproject
> python manage.py syncdb
> python manage.py runserver

結果

最後に、すべての準備が整いました。デフォルトのDjango開発環境では、アップロードされたドキュメントのリストはで確認できますlocalhost:8000/list/。今日、ファイルは/ path / to / myproject / media / documents / 2011/12/17 /にアップロードされ、リストから開くことができます。

この答えが、私を助けてくれたのと同じくらい誰かを助けてくれることを願っています。


9
ファイルのアップロードを示すdjango docs内の場所を見つけました。この回答の例は素晴らしいですが、django docsの情報は新しいリリースで最新の状態に保たれます。 docs.djangoproject.com/en/dev/topics/http/file-uploads
TaiwanGrapefruitTea

1
この例はDjango "1.5"では機能しません。HTMLではに{% url list %}なり{% url "list" %}ます。
Matthieu Riegler 2013年

4
どうもありがとうございました 。それは本当に私のために働きます。ただし、今後のビューアの場合は、gitHubのコードをチェックして、新しいバージョンのPythonとDjangoとの互換性を確認する必要があります。たとえば、CSRFエラーを回避するには、views.py、render_to_response()をrender(request、...、)に置き換える必要があります。乾杯。
Huy Than

1
フォームなしでこれを行うことは可能ですか?
Roel

1
ファイルは.zipまたは他の圧縮ファイルにすることができますか?
qg_java_17137 2017年

75

一般的に言えば、「実際に動作する例を取得する」だけの場合は、「コードの記述を開始する」のが最善です。ここに役立つコードはありません。そのため、質問への回答がより多くの作業になります。

ファイルを取得したい場合は、htmlファイルのどこかに次のようなものが必要です。

<form method="post" enctype="multipart/form-data">
    <input type="file" name="myfile" />
    <input type="submit" name="submit" value="Upload" />
</form>

これにより、参照ボタン、アクションを開始(フォームを送信)するためのアップロードボタンが表示され、Djangoが認識できるようにenctypeが記録されます。 request.FILES

ビューのどこかでファイルにアクセスできます

def myview(request):
    request.FILES['myfile'] # this is my file

ファイルアップロードドキュメントに大量の情報があります

このページをよく読んで、コードを書き始めることをお勧めします。機能しない場合は、例とスタックトレースを使用して戻ってきます。


10
ヘンリーありがとう。実際、私はドキュメントを読んでいくつかのコードを書きましたが、ドキュメントにギャップがあるため(たとえば、「どこかからインポートhandle_uploaded_file」など)、コードに欠陥があるため、実際の例から始めることができればはるかに良いと思いました。
qliq 2011年

26
qliqに同意します。単純な実際の例は、ドキュメントではなく初心者を
動かす

11
enctype="multipart/form-data"私はこの仕事、感謝を作るために必要なもの!
john-charles 2013年

5
フォームタグ内の{%csrf_token%}をお見逃しなく。
jonincanada 2015年

FORMS.PYからのフォームなしでこれを行うことは可能ですか?
Roel

71

デモ

Django 3で動作するgithub repoを参照してください

最小限のDjangoファイルアップロードの例

1. djangoプロジェクトを作成する

startproject ::を実行します。

$ django-admin.py startproject sample

これで、フォルダー(サンプル)が作成されました。

2.アプリを作成する

アプリを作成::

$ cd sample
$ python manage.py startapp uploader

uploaderこれらのファイルを含むフォルダ()が作成されます::

uploader/
  __init__.py
  admin.py
  app.py
  models.py
  tests.py
  views.py
  migrations/
    __init__.py

3. settings.pyを更新します

上のsample/settings.pyアドオン'uploader'INSTALLED_APPSと追加MEDIA_ROOTしてMEDIA_URL、すなわち::

INSTALLED_APPS = [
    'uploader',
    ...<other apps>...      
]

MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'

4. urls.pyを更新する

sample/urls.pyアドオン::

...<other imports>...
from django.conf import settings
from django.conf.urls.static import static
from uploader import views as uploader_views

urlpatterns = [
    ...<other url patterns>...
    path('', uploader_views.UploadView.as_view(), name='fileupload'),
]+ static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

5. models.pyを更新します

更新uploader/models.py::

from django.db import models
class Upload(models.Model):
    upload_file = models.FileField()    
    upload_date = models.DateTimeField(auto_now_add =True)

6. views.pyを更新する

更新uploader/views.py::

from django.views.generic.edit import CreateView
from django.urls import reverse_lazy
from .models import Upload
class UploadView(CreateView):
    model = Upload
    fields = ['upload_file', ]
    success_url = reverse_lazy('fileupload')
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['documents'] = Upload.objects.all()
        return context

7.テンプレートを作成する

フォルダーsample / uploader / templates / uploaderを作成します

ファイルupload_form.html ieを作成しますsample/uploader/templates/uploader/upload_form.html::

<div style="padding:40px;margin:40px;border:1px solid #ccc">
    <h1>Django File Upload</h1>
    <form method="post" enctype="multipart/form-data">
      {% csrf_token %}
      {{ form.as_p }}
      <button type="submit">Submit</button>
    </form><hr>
    <ul>
    {% for document in documents %}
        <li>
            <a href="{{ document.upload_file.url }}">{{ document.upload_file.name }}</a>
            <small>({{ document.upload_file.size|filesizeformat }}) - {{document.upload_date}}</small>
        </li>
    {% endfor %}
    </ul>
</div>

8.データベースを同期する

データベースとrunserverを同期する::

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

http:// localhost:8000 /にアクセスします


2
最後の行を除いて完璧-する必要がありますlocalhost.com:8000/upload >これは、Djangoの1.6とPython 3.3のために働きました。
Steve

5
再利用可能なdjangoアプリのデザインパターンの+1
Marcel

1
AkseliがFileFieldしばらく使用しましたsuhailがを使用しましたImageField。誰かが選択について説明してもらえますか?
dvtan 2015年

@dtgqで使用するように回答を更新しましたFileFieldImageField画像のみアップロードする必要があります。アップデートはDjango 1.11で動作します。
suhailvs 2017

Django 2.0でテストされ、完全に動作しました
18

29

私はdjangoのドキュメントを混乱させていると言わざるを得ません。また、最も単純な例では、なぜフォームが言及されているのですか?私がviews.pyで作業しなければならない例は次のとおりです:-

for key, file in request.FILES.items():
    path = file.name
    dest = open(path, 'w')
    if file.multiple_chunks:
        for c in file.chunks():
            dest.write(c)
    else:
        dest.write(file.read())
    dest.close()

htmlファイルは次のコードのようになりますが、この例では1つのファイルのみをアップロードし、ファイルを保存するコードは多数を処理します。

<form action="/upload_file/" method="post" enctype="multipart/form-data">{% csrf_token %}
<label for="file">Filename:</label>
<input type="file" name="file" id="file" />
<br />
<input type="submit" name="submit" value="Submit" />
</form>

これらの例は私のコードではなく、私が見つけた他の2つの例から除外されています。私はジャンゴの比較的初心者なので、いくつかの重要なポイントを見逃している可能性があります。


3
a FileFieldとa を使用しない場合は+1 model.Form。初心者(および簡単なタスク)の場合、上記のようにアップロードされたファイルを手動で処理する方が混乱が少なくなります。
AneesAhmed777 2017

dest = open(path、 'wb')(ファイルがバイトで書き込まれる場合)
Bipul Roy

20

同様の要件もありました。ネット上のほとんどの例は、私が使用したくないモデルとフォームを作成することを求めています。これが私の最終的なコードです。

if request.method == 'POST':
    file1 = request.FILES['file']
    contentOfFile = file1.read()
    if file1:
        return render(request, 'blogapp/Statistics.html', {'file': file1, 'contentOfFile': contentOfFile})

そしてアップロードするHTMLで私は書いた:

{% block content %}
    <h1>File content</h1>
    <form action="{% url 'blogapp:uploadComplete'%}" method="post" enctype="multipart/form-data">
         {% csrf_token %}
        <input id="uploadbutton" type="file" value="Browse" name="file" accept="text/csv" />
        <input type="submit" value="Upload" />
    </form>
    {% endblock %}

以下は、ファイルのコンテンツを表示するHTMLです。

{% block content %}
    <h3>File uploaded successfully</h3>
    {{file.name}}
    </br>content = {{contentOfFile}}
{% endblock %}

アップロードを保存せずに、ファイルのコンテンツを使用したい場合があるので、良い…
nemesisfixx

17

ヘンリーの例を拡張する:

import tempfile
import shutil

FILE_UPLOAD_DIR = '/home/imran/uploads'

def handle_uploaded_file(source):
    fd, filepath = tempfile.mkstemp(prefix=source.name, dir=FILE_UPLOAD_DIR)
    with open(filepath, 'wb') as dest:
        shutil.copyfileobj(source, dest)
    return filepath

handle_uploaded_fileアップロードしたファイルオブジェクトを使用して、ビューからこの関数を呼び出すことができます。これにより、ファイルシステムに一意の名前(アップロードされた元のファイルのファイル名が前に付いた名前)でファイルが保存され、保存されたファイルの完全パスが返されます。パスをデータベースに保存し、後でファイルを使用して何かを行うことができます。


イムラン、私は自分のビューでコードを試しましたが、次のエラーが発生しました: 'WSGIRequest'オブジェクトに属性 'name'がありません。
qliq '05年

2
アップロードされたファイルオブジェクト(request.FILES['myfile'])をそれ自体handle_uploaded_fileではなくに渡しますrequest
イムラン、

データベースに直接保存できますか?stackoverflow.com/questions/24705246/...
AlexandruC

これを使用するprefix=source.nameと、ファイルの末尾に余分な文字が追加され、ファイル拡張子がめちゃくちゃになります。たとえば、upload.csvに変更されましたupload.csv5334。それをsuffix=source.name修正するために変更しました。
Tahreem Iqbal

13

ここでそれはあなたを助けるかもしれません:models.pyにファイルフィールドを作成する

ファイルをアップロードするには(admin.py内):

def save_model(self, request, obj, form, change):
    url = "http://img.youtube.com/vi/%s/hqdefault.jpg" %(obj.video)
    url = str(url)

    if url:
        temp_img = NamedTemporaryFile(delete=True)
        temp_img.write(urllib2.urlopen(url).read())
        temp_img.flush()
        filename_img = urlparse(url).path.split('/')[-1]
        obj.image.save(filename_img,File(temp_img)

テンプレートでもそのフィールドを使用します。


1
これは、保存するファイルを手動で調整する必要がある場合に便利です。その場合、このセクションも必要になる場合があります。docs.djangoproject.com
en

11

djangoバージョンのFine Uploaderでサーバーの例を参照できます。 https://github.com/FineUploader/server-examples/tree/master/python/django-fine-uploader

それは非常にエレガントで、最も重要なのは、注目のjs libを提供することです。テンプレートはserver-examplesに含まれていませんが、そのWebサイトでデモを見つけることができます。Fine Uploader:http : //fineuploader.com/demos.html

django-fine-uploader

views.py

UploadViewは、投稿と削除のリクエストをそれぞれのハンドラにディスパッチします。

class UploadView(View):

    @csrf_exempt
    def dispatch(self, *args, **kwargs):
        return super(UploadView, self).dispatch(*args, **kwargs)

    def post(self, request, *args, **kwargs):
        """A POST request. Validate the form and then handle the upload
        based ont the POSTed data. Does not handle extra parameters yet.
        """
        form = UploadFileForm(request.POST, request.FILES)
        if form.is_valid():
            handle_upload(request.FILES['qqfile'], form.cleaned_data)
            return make_response(content=json.dumps({ 'success': True }))
        else:
            return make_response(status=400,
                content=json.dumps({
                    'success': False,
                    'error': '%s' % repr(form.errors)
                }))

    def delete(self, request, *args, **kwargs):
        """A DELETE request. If found, deletes a file with the corresponding
        UUID from the server's filesystem.
        """
        qquuid = kwargs.get('qquuid', '')
        if qquuid:
            try:
                handle_deleted_file(qquuid)
                return make_response(content=json.dumps({ 'success': True }))
            except Exception, e:
                return make_response(status=400,
                    content=json.dumps({
                        'success': False,
                        'error': '%s' % repr(e)
                    }))
        return make_response(status=404,
            content=json.dumps({
                'success': False,
                'error': 'File not present'
            }))

forms.py

class UploadFileForm(forms.Form):

    """ This form represents a basic request from Fine Uploader.
    The required fields will **always** be sent, the other fields are optional
    based on your setup.
    Edit this if you want to add custom parameters in the body of the POST
    request.
    """
    qqfile = forms.FileField()
    qquuid = forms.CharField()
    qqfilename = forms.CharField()
    qqpartindex = forms.IntegerField(required=False)
    qqchunksize = forms.IntegerField(required=False)
    qqpartbyteoffset = forms.IntegerField(required=False)
    qqtotalfilesize = forms.IntegerField(required=False)
    qqtotalparts = forms.IntegerField(required=False)

7

このアプローチにデメリットがあるかどうかはわかりませんが、views.pyでさらに最小限に抑えます。

entry = form.save()

# save uploaded file
if request.FILES['myfile']:
    entry.myfile.save(request.FILES['myfile']._name, request.FILES['myfile'], True)

0

私は同様の問題に直面し、django管理サイトで解決しました。

# models
class Document(models.Model):
    docfile = models.FileField(upload_to='documents/Temp/%Y/%m/%d')

    def doc_name(self):
        return self.docfile.name.split('/')[-1] # only the name, not full path

# admin
from myapp.models import Document
class DocumentAdmin(admin.ModelAdmin):
    list_display = ('doc_name',)
admin.site.register(Document, DocumentAdmin)

[ここにリンクの説明を入力] [1] [ここにリンクの説明を入力] [2] [1]:youtu.be/0tNZB3dyopY [2]:youtu.be/klhMYMc3PlY
uda123
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.