Réponses:
Ouf, la documentation Django n'a vraiment pas de bon exemple à ce sujet. J'ai passé plus de 2 heures à déterrer toutes les pièces pour comprendre comment cela fonctionne. Avec cette connaissance, j'ai mis en œuvre un projet qui permet de télécharger des fichiers et de les afficher sous forme de liste. Pour télécharger la source du projet, visitez https://github.com/axelpale/minimal-django-file-upload-example ou clonez-le:
> git clone https://github.com/axelpale/minimal-django-file-upload-example.git
Mise à jour 2013-01-30: La source de GitHub a également une implémentation pour Django 1.4 en plus de 1.3. Même s'il y a peu de changements, le tutoriel suivant est également utile pour 1.4.
Mise à jour 2013-05-10: Implémentation de Django 1.5 sur GitHub. Changements mineurs dans la redirection dans urls.py et utilisation de la balise de modèle d'URL dans list.html. Merci à hubert3 pour l'effort.
Mise à jour 2013-12-07: Django 1.6 pris en charge sur GitHub. Une importation a changé dans myapp / urls.py. Merci à Arthedian .
Mise à jour 2015-03-17: Django 1.7 pris en charge sur GitHub, grâce à aronysidoro .
Mise à jour 2015-09-04: Django 1.8 supporté sur GitHub, grâce à nerogit .
Mise à jour 2016-07-03: Django 1.9 pris en charge sur GitHub, grâce à daavve et nerogit
Un projet Django 1.3 de base avec une seule application et un média / répertoire pour les téléchargements.
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
Pour télécharger et servir des fichiers, vous devez spécifier où Django stocke les fichiers téléchargés et à partir de quelle URL Django les sert. MEDIA_ROOT et MEDIA_URL sont dans settings.py par défaut mais ils sont vides. Voir les premières lignes de Django Managing Files pour plus de détails. N'oubliez pas également de définir la base de données et d'ajouter 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',
)
Ensuite, vous avez besoin d'un modèle avec un FileField. Ce champ particulier stocke par exemple des fichiers dans les médias / documents / 2011/12/24 / en fonction de la date actuelle et de MEDIA_ROOT. Voir la référence FileField .
# -*- coding: utf-8 -*-
from django.db import models
class Document(models.Model):
docfile = models.FileField(upload_to='documents/%Y/%m/%d')
Pour bien gérer le téléchargement, vous avez besoin d'un formulaire. Ce formulaire ne comporte qu'un seul champ mais cela suffit. Voir la référence du formulaire FileField pour plus de détails.
# -*- coding: utf-8 -*-
from django import forms
class DocumentForm(forms.Form):
docfile = forms.FileField(
label='Select a file',
help_text='max. 42 megabytes'
)
Une vue où toute la magie opère. Faites attention à la façon dont ils request.FILES
sont traités. Pour moi, il était vraiment difficile de repérer le fait qu'il request.FILES['docfile']
peut être enregistré dans des modèles. FileField comme ça. La fonction save () du modèle gère automatiquement le stockage du fichier dans le système de fichiers.
# -*- 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 ne sert pas MEDIA_ROOT par défaut. Ce serait dangereux dans un environnement de production. Mais au stade du développement, nous pourrions écourter. Faites attention à la dernière ligne. Cette ligne permet à Django de servir des fichiers à partir de MEDIA_URL. Cela ne fonctionne qu'en phase de développement.
Voir la référence django.conf.urls.static.static pour plus de détails. Voir également cette discussion sur la diffusion de fichiers multimédias .
# -*- 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)
Pour rendre la vue accessible, vous devez lui spécifier des URL. Rien de spécial ici.
# -*- coding: utf-8 -*-
from django.conf.urls import patterns, url
urlpatterns = patterns('myapp.views',
url(r'^list/$', 'list', name='list'),
)
La dernière partie: modèle pour la liste et le formulaire de téléchargement en dessous. Le formulaire doit avoir l'attribut enctype défini sur "multipart / form-data" et la méthode définie sur "post" pour permettre le téléchargement vers Django. Consultez la documentation relative aux téléchargements de fichiers pour plus de détails.
Le FileField possède de nombreux attributs qui peuvent être utilisés dans les modèles. Par exemple {{document.docfile.url}} et {{document.docfile.name}} comme dans le modèle. Pour en savoir plus, consultez l' article Utilisation des fichiers dans les modèles et la documentation de l'objet Fichier .
<!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>
Exécutez simplement syncdb et runserver.
> cd myproject
> python manage.py syncdb
> python manage.py runserver
Enfin, tout est prêt. Dans l'environnement de développement Django par défaut, la liste des documents téléchargés peut être consultée sur localhost:8000/list/
. Aujourd'hui, les fichiers sont téléchargés dans / path / to / myproject / media / documents / 2011/12/17 / et peuvent être ouverts à partir de la liste.
J'espère que cette réponse aidera quelqu'un autant qu'elle m'aurait aidé.
{% url list %}
devient {% url "list" %}
.
De manière générale, lorsque vous essayez de «simplement obtenir un exemple de travail», il est préférable de «commencer à écrire du code». Il n'y a pas de code ici pour vous aider, donc cela fait beaucoup plus de travail pour nous de répondre à la question.
Si vous voulez récupérer un fichier, vous avez besoin de quelque chose comme ça dans un fichier html quelque part:
<form method="post" enctype="multipart/form-data">
<input type="file" name="myfile" />
<input type="submit" name="submit" value="Upload" />
</form>
Cela vous donnera le bouton de navigation, un bouton de téléchargement pour démarrer l'action (soumettre le formulaire) et notez le code afin que Django sache vous donner request.FILES
Dans une vue quelque part, vous pouvez accéder au fichier avec
def myview(request):
request.FILES['myfile'] # this is my file
Il y a une énorme quantité d'informations dans les documents de téléchargement de fichiers
Je vous recommande de lire attentivement la page et de commencer à écrire du code - puis de revenir avec des exemples et des traces de pile lorsque cela ne fonctionne pas.
enctype="multipart/form-data"
ce dont j'avais besoin pour faire ce travail, merci!
Voir le dépôt github , fonctionne avec Django 3
Exécutez startproject ::
$ django-admin.py startproject sample
maintenant un dossier ( exemple ) est créé.
Créer une application ::
$ cd sample
$ python manage.py startapp uploader
Maintenant, un dossier ( uploader
) avec ces fichiers est créé ::
uploader/
__init__.py
admin.py
app.py
models.py
tests.py
views.py
migrations/
__init__.py
Sur sample/settings.py
add 'uploader'
to INSTALLED_APPS
et add MEDIA_ROOT
and MEDIA_URL
, ie:
INSTALLED_APPS = [
'uploader',
...<other apps>...
]
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
en sample/urls.py
plus ::
...<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)
mise à jour uploader/models.py
::
from django.db import models
class Upload(models.Model):
upload_file = models.FileField()
upload_date = models.DateTimeField(auto_now_add =True)
mise à jour 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
Créer un exemple de dossier / uploader / templates / uploader
Créez un fichier 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>
Syncronize base de données et runserver ::
$ python manage.py makemigrations
$ python manage.py migrate
$ python manage.py runserver
visitez http: // localhost: 8000 /
FileField
certain temps suhail a utilisé un ImageField
, quelqu'un pourrait-il expliquer les choix?
FileField
. ImageField
doit pour l'image uniquement télécharger. la mise à jour fonctionnera avec Django 1.11.
Je dois dire que je trouve la documentation de django déroutante. Aussi pour l'exemple le plus simple, pourquoi les formulaires sont-ils mentionnés? L'exemple que j'ai pu travailler dans le views.py est: -
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()
Le fichier html ressemble au code ci-dessous, bien que cet exemple ne télécharge qu'un seul fichier et que le code pour enregistrer les fichiers en gère plusieurs: -
<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>
Ces exemples ne sont pas mon code, ils ont été choisis parmi deux autres exemples que j'ai trouvés. Je suis un débutant relatif à Django, il est donc très probable que je manque un point clé.
FileField
et a model.Form
. Pour les débutants (et pour les tâches triviales), le traitement manuel des fichiers téléchargés comme indiqué ci-dessus est moins déroutant.
J'avais également la même exigence. La plupart des exemples sur net demandent de créer des modèles et des formulaires que je ne voulais pas utiliser. Voici mon code final.
if request.method == 'POST':
file1 = request.FILES['file']
contentOfFile = file1.read()
if file1:
return render(request, 'blogapp/Statistics.html', {'file': file1, 'contentOfFile': contentOfFile})
Et en HTML pour télécharger, j'ai écrit:
{% 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 %}
Voici le code HTML qui affiche le contenu du fichier:
{% block content %}
<h3>File uploaded successfully</h3>
{{file.name}}
</br>content = {{contentOfFile}}
{% endblock %}
S'étendant sur l'exemple d'Henry :
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
Vous pouvez appeler cette handle_uploaded_file
fonction depuis votre vue avec l'objet fichier téléchargé. Cela enregistrera le fichier avec un nom unique (préfixé par le nom de fichier du fichier téléchargé d'origine) dans le système de fichiers et renverra le chemin complet du fichier enregistré. Vous pouvez enregistrer le chemin dans la base de données et faire quelque chose avec le fichier plus tard.
request.FILES['myfile']
) à handle_uploaded_file
, pas le request
lui - même.
prefix=source.name
, des caractères supplémentaires ont été ajoutés à la fin du fichier, gâchant l'extension du fichier. Par exemple, upload.csv
changé en upload.csv5334
. Le changer pour le suffix=source.name
réparer pour moi.
Ici, cela peut vous aider: créez un champ de fichier dans votre models.py
Pour télécharger le fichier (dans votre 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)
et utilisez également ce champ dans votre modèle.
Vous pouvez vous référer aux exemples de serveur dans Fine Uploader, qui a la version django. https://github.com/FineUploader/server-examples/tree/master/python/django-fine-uploader
Il est très élégant et le plus important de tous, il fournit la librairie js en vedette. Le modèle n'est pas inclus dans les exemples de serveur, mais vous pouvez trouver une démo sur son site Web. Fine Uploader: http://fineuploader.com/demos.html
views.py
UploadView envoie la demande de publication et de suppression aux gestionnaires respectifs.
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)
J'ai fait face au problème similaire et résolu par le site d'administration de 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)