Antworten:
Puh, die Django-Dokumentation hat wirklich kein gutes Beispiel dafür. Ich habe über 2 Stunden damit verbracht, alle Teile auszugraben, um zu verstehen, wie das funktioniert. Mit diesem Wissen habe ich ein Projekt implementiert, das es ermöglicht, Dateien hochzuladen und als Liste anzuzeigen. Um die Quelle für das Projekt herunterzuladen, besuchen Sie https://github.com/axelpale/minimal-django-file-upload-example oder klonen Sie sie:
> git clone https://github.com/axelpale/minimal-django-file-upload-example.git
Update 30.01.2013: Die Quelle bei GitHub hat neben 1.3 auch eine Implementierung für Django 1.4. Obwohl es nur wenige Änderungen gibt, ist das folgende Tutorial auch für 1.4 nützlich.
Update 10.05.2013: Implementierung für Django 1.5 bei GitHub. Kleinere Änderungen bei der Umleitung in urls.py und Verwendung des URL-Vorlagen-Tags in list.html. Danke an hubert3 für die Mühe.
Update 07.12.2013: Django 1.6 wird bei GitHub unterstützt. Ein Import wurde in myapp / urls.py geändert. Danke geht an Arthedian .
Update 17.03.2015: Django 1.7 wird dank aronysidoro bei GitHub unterstützt .
Update 04.09.2015: Django 1.8 wird dank nerogit bei GitHub unterstützt .
Update 03.07.2016: Django 1.9 wird bei GitHub dank Daavve und Nerogit unterstützt
Ein einfaches Django 1.3-Projekt mit einer einzigen App und einem Medien- / Verzeichnis zum Hochladen.
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
Um Dateien hochzuladen und bereitzustellen, müssen Sie angeben, wo Django hochgeladene Dateien speichert und von welcher URL Django sie bereitstellt. MEDIA_ROOT und MEDIA_URL befinden sich standardmäßig in settings.py, sind jedoch leer. Weitere Informationen finden Sie in den ersten Zeilen in Django Managing Files . Denken Sie daran, auch die Datenbank festzulegen und myapp zu INSTALLED_APPS hinzuzufügen
...
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',
)
Als nächstes benötigen Sie ein Modell mit einem FileField. In diesem speziellen Feld werden Dateien gespeichert, z. B. in Medien / Dokumenten / 2011/12/24 / basierend auf dem aktuellen Datum und MEDIA_ROOT. Siehe FileField-Referenz .
# -*- coding: utf-8 -*-
from django.db import models
class Document(models.Model):
docfile = models.FileField(upload_to='documents/%Y/%m/%d')
Um den Upload gut zu handhaben, benötigen Sie ein Formular. Dieses Formular hat nur ein Feld, aber das reicht aus. Weitere Informationen finden Sie in der Referenz zu 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'
)
Eine Ansicht, in der all die Magie passiert. Achten Sie darauf, wie request.FILES
damit umgegangen wird. Für mich war es wirklich schwer zu erkennen, dass request.FILES['docfile']
es in Modellen gespeichert werden kann. FileField einfach so. Mit save () des Modells wird die Datei automatisch im Dateisystem gespeichert.
# -*- 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)
)
Django bedient standardmäßig nicht MEDIA_ROOT. Das wäre in der Produktionsumgebung gefährlich. Aber in der Entwicklungsphase könnten wir abkürzen. Achten Sie auf die letzte Zeile. Diese Zeile ermöglicht es Django, Dateien von MEDIA_URL bereitzustellen. Dies funktioniert nur in der Entwicklungsphase.
Weitere Informationen finden Sie in der Referenz zu django.conf.urls.static.static . Siehe auch diese Diskussion zum Bereitstellen von Mediendateien .
# -*- 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)
Um die Ansicht zugänglich zu machen, müssen Sie URLs dafür angeben. Hier ist nichts Besonderes.
# -*- coding: utf-8 -*-
from django.conf.urls import patterns, url
urlpatterns = patterns('myapp.views',
url(r'^list/$', 'list', name='list'),
)
Der letzte Teil: Vorlage für die Liste und das Upload-Formular darunter. Das Formular muss ein enctype-Attribut auf "multipart / form-data" und eine Methode auf "post" setzen, um das Hochladen nach Django zu ermöglichen. Weitere Informationen finden Sie in der Dokumentation zum Hochladen von Dateien .
Das FileField verfügt über viele Attribute, die in Vorlagen verwendet werden können. ZB {{document.docfile.url}} und {{document.docfile.name}} wie in der Vorlage. Weitere Informationen hierzu finden Sie im Artikel Verwenden von Dateien in Modellen und in der Dokumentation zum Dateiobjekt .
<!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>
Führen Sie einfach syncdb und runserver aus.
> cd myproject
> python manage.py syncdb
> python manage.py runserver
Endlich ist alles fertig. In der Standard-Django-Entwicklungsumgebung kann die Liste der hochgeladenen Dokumente unter angezeigt werden localhost:8000/list/
. Heute werden die Dateien nach / path / to / myproject / media / documents / 2011/12/17 / hochgeladen und können aus der Liste geöffnet werden.
Ich hoffe, diese Antwort hilft jemandem so sehr, wie es mir geholfen hätte.
{% url list %}
wird {% url "list" %}
.
Wenn Sie versuchen, nur ein funktionierendes Beispiel zu erhalten, ist es im Allgemeinen am besten, einfach mit dem Schreiben von Code zu beginnen. Es gibt hier keinen Code, der Ihnen dabei hilft, sodass die Beantwortung der Frage für uns viel einfacher ist.
Wenn Sie eine Datei abrufen möchten, benötigen Sie irgendwo in einer HTML-Datei Folgendes:
<form method="post" enctype="multipart/form-data">
<input type="file" name="myfile" />
<input type="submit" name="submit" value="Upload" />
</form>
Dadurch erhalten Sie die Schaltfläche zum Durchsuchen, eine Schaltfläche zum Hochladen, um die Aktion zu starten (senden Sie das Formular) und den Enctype zu notieren, damit Django Sie kennen kann request.FILES
In einer Ansicht irgendwo können Sie mit auf die Datei zugreifen
def myview(request):
request.FILES['myfile'] # this is my file
Die Datei-Upload-Dokumente enthalten eine Vielzahl von Informationen
Ich empfehle Ihnen, die Seite gründlich zu lesen und einfach mit dem Schreiben von Code zu beginnen. Geben Sie dann Beispiele und Stapelspuren zurück, wenn dies nicht funktioniert.
enctype="multipart/form-data"
was ich brauchte, um diese Arbeit zu machen, danke!
Siehe das Github-Repo , funktioniert mit Django 3
Führen Sie startproject :: aus.
$ django-admin.py startproject sample
Jetzt wird ein Ordner ( Beispiel ) erstellt.
Erstellen Sie eine App ::
$ cd sample
$ python manage.py startapp uploader
Nun wird ein Ordner ( uploader
) mit diesen Dateien erstellt ::
uploader/
__init__.py
admin.py
app.py
models.py
tests.py
views.py
migrations/
__init__.py
Auf sample/settings.py
Add 'uploader'
zu INSTALLED_APPS
und fügen MEDIA_ROOT
und MEDIA_URL
, dh ::
INSTALLED_APPS = [
'uploader',
...<other apps>...
]
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
in sample/urls.py
add ::
...<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)
update uploader/models.py
::
from django.db import models
class Upload(models.Model):
upload_file = models.FileField()
upload_date = models.DateTimeField(auto_now_add =True)
update 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
Erstellen Sie einen Ordner sample / uploader / templates / uploader
Erstellen Sie eine Datei upload_form.html dh 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>
Synchronisieren Sie Datenbank und Runserver ::
$ python manage.py makemigrations
$ python manage.py migrate
$ python manage.py runserver
Besuchen Sie http: // localhost: 8000 /
FileField
Weile suhail benutzte eine ImageField
, könnte jemand bitte die Entscheidungen erklären?
FileField
. ImageField
muss nur für bild hochladen. Das Update funktioniert mit Django 1.11.
Ich muss sagen, ich finde die Dokumentation bei Django verwirrend. Auch für das einfachste Beispiel, warum werden Formulare erwähnt? Das Beispiel, das ich in views.py arbeiten musste, ist: -
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()
Die HTML-Datei sieht wie folgt aus: In diesem Beispiel wird jedoch nur eine Datei hochgeladen, und der Code zum Speichern der Dateien verarbeitet viele: -
<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>
Diese Beispiele sind nicht mein Code, sie wurden aus zwei anderen Beispielen ausgewählt, die ich gefunden habe. Ich bin ein relativer Anfänger von Django, daher ist es sehr wahrscheinlich, dass mir ein wichtiger Punkt fehlt.
FileField
und a model.Form
. Für Anfänger (und für triviale Aufgaben) ist die manuelle Verarbeitung hochgeladener Dateien wie oben gezeigt weniger verwirrend.
Ich hatte auch die ähnliche Anforderung. Die meisten Beispiele im Internet fordern das Erstellen von Modellen und Formularen, die ich nicht verwenden wollte. Hier ist mein endgültiger Code.
if request.method == 'POST':
file1 = request.FILES['file']
contentOfFile = file1.read()
if file1:
return render(request, 'blogapp/Statistics.html', {'file': file1, 'contentOfFile': contentOfFile})
Und in HTML zum Hochladen schrieb ich:
{% 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 %}
Das Folgende ist der HTML-Code, der den Inhalt der Datei anzeigt:
{% block content %}
<h3>File uploaded successfully</h3>
{{file.name}}
</br>content = {{contentOfFile}}
{% endblock %}
Erweiterung auf Henrys Beispiel :
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
Sie können diese handle_uploaded_file
Funktion aus Ihrer Sicht mit dem hochgeladenen Dateiobjekt aufrufen . Dadurch wird die Datei unter einem eindeutigen Namen (vorangestellt mit dem Dateinamen der ursprünglich hochgeladenen Datei) im Dateisystem gespeichert und der vollständige Pfad der gespeicherten Datei zurückgegeben. Sie können den Pfad in der Datenbank speichern und später etwas mit der Datei tun.
request.FILES['myfile']
) an handle_uploaded_file
, nicht an das request
selbst.
prefix=source.name
wurden zusätzliche Zeichen am Ende der Datei hinzugefügt, wodurch die Dateierweiterung durcheinander gebracht wurde. ZB upload.csv
wurde geändert zu upload.csv5334
. Ändern Sie es, um suffix=source.name
es für mich zu beheben.
Hier kann es Ihnen helfen: Erstellen Sie ein Dateifeld in Ihrer models.py
Zum Hochladen der Datei (in Ihrer 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)
und verwenden Sie dieses Feld auch in Ihrer Vorlage.
Sie können auf Serverbeispiele in Fine Uploader verweisen, das die Django-Version hat. https://github.com/FineUploader/server-examples/tree/master/python/django-fine-uploader
Es ist sehr elegant und vor allem bietet es eine vorgestellte js lib. Vorlage ist nicht in Server-Beispielen enthalten, aber Sie können Demo auf seiner Website finden. Feiner Uploader: http://fineuploader.com/demos.html
views.py
UploadView sendet Post- und Löschanforderungen an die jeweiligen Handler.
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)
Ich stand vor einem ähnlichen Problem und wurde von der Django-Admin-Site gelöst.
# 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)