Risposte:
Accidenti, la documentazione di Django non ha davvero un buon esempio al riguardo. Ho trascorso più di 2 ore a scavare tutti i pezzi per capire come funziona. Con questa conoscenza ho implementato un progetto che rende possibile caricare file e mostrarli come elenco. Per scaricare la fonte per il progetto, visitare https://github.com/axelpale/minimal-django-file-upload-example o clonarlo:
> git clone https://github.com/axelpale/minimal-django-file-upload-example.git
Aggiornamento 30-01-2013: l'origine di GitHub ha anche un'implementazione per Django 1.4 oltre a 1.3. Anche se ci sono alcune modifiche, il seguente tutorial è utile anche per 1.4.
Aggiornamento 2013-05-10: Implementazione per Django 1.5 su GitHub. Piccole modifiche al reindirizzamento in urls.py e all'utilizzo del tag del modello url in list.html. Grazie a hubert3 per lo sforzo.
Aggiornamento 2013-12-07: Django 1.6 supportato su GitHub. Un'importazione è cambiata in myapp / urls.py. Grazie va ad Arthedian .
Aggiornamento 17-03-2015: Django 1.7 supportato su GitHub, grazie ad aronysidoro .
Aggiornamento 2015-09-04: Django 1.8 supportato su GitHub, grazie a nerogit .
Aggiornamento 03/07/2016: Django 1.9 supportato su GitHub, grazie a daavve e nerogit
Un progetto di base Django 1.3 con un'unica app e directory media / per i caricamenti.
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
Per caricare e pubblicare file, devi specificare dove Django memorizza i file caricati e da quale URL Django li serve. MEDIA_ROOT e MEDIA_URL sono in settings.py per impostazione predefinita ma sono vuoti. Vedi le prime righe in Django Managing Files per i dettagli. Ricorda inoltre di impostare il database e aggiungere myapp a 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',
)
Successivamente è necessario un modello con un FileField. Questo particolare campo memorizza i file, ad esempio su media / documenti / 2011/12/24 / in base alla data corrente e MEDIA_ROOT. Vedi riferimento FileField .
# -*- coding: utf-8 -*-
from django.db import models
class Document(models.Model):
docfile = models.FileField(upload_to='documents/%Y/%m/%d')
Per gestire correttamente il caricamento, è necessario un modulo. Questo modulo ha solo un campo ma è abbastanza. Per ulteriori dettagli, consultare il riferimento al modulo FileField .
# -*- coding: utf-8 -*-
from django import forms
class DocumentForm(forms.Form):
docfile = forms.FileField(
label='Select a file',
help_text='max. 42 megabytes'
)
Una vista in cui accade tutta la magia. Prestare attenzione a come request.FILES
vengono gestiti. Per me, è stato davvero difficile individuare il fatto che request.FILES['docfile']
può essere salvato su modelli. FileField in questo modo. Save () del modello gestisce automaticamente la memorizzazione del file nel filesystem.
# -*- 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 non serve MEDIA_ROOT per impostazione predefinita. Sarebbe pericoloso nell'ambiente di produzione. Ma in fase di sviluppo, potremmo tagliare. Presta attenzione all'ultima riga. Questa linea consente a Django di pubblicare file da MEDIA_URL. Funziona solo in fase di sviluppo.
Vedi riferimento django.conf.urls.static.static per i dettagli. Vedi anche questa discussione sulla pubblicazione di file multimediali .
# -*- 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)
Per rendere accessibile la vista, è necessario specificare gli URL per essa. Niente di speciale qui.
# -*- coding: utf-8 -*-
from django.conf.urls import patterns, url
urlpatterns = patterns('myapp.views',
url(r'^list/$', 'list', name='list'),
)
L'ultima parte: modello per l'elenco e il modulo di caricamento sottostante. Il modulo deve avere l'attributo enctype impostato su "multipart / form-data" e il metodo impostato su "post" per rendere possibile il caricamento su Django. Consulta la documentazione relativa ai caricamenti di file per i dettagli.
FileField ha molti attributi che possono essere utilizzati nei modelli. Ad esempio {{document.docfile.url}} e {{document.docfile.name}} come nel modello. Per ulteriori informazioni, consultare l' articolo sull'utilizzo dei file nei modelli e la documentazione dell'oggetto File .
<!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>
Basta eseguire syncdb e RunServer.
> cd myproject
> python manage.py syncdb
> python manage.py runserver
Finalmente è tutto pronto. Nell'ambiente di sviluppo di Django predefinito è possibile visualizzare l'elenco dei documenti caricati su localhost:8000/list/
. Oggi i file vengono caricati in / percorso / in / myproject / media / documenti / 2011/12/17 / e possono essere aperti dall'elenco.
Spero che questa risposta possa aiutare qualcuno tanto quanto mi avrebbe aiutato.
{% url list %}
diventa {% url "list" %}
.
In generale, quando si sta tentando di "solo ottenere un esempio funzionante", è meglio "iniziare a scrivere codice". Non esiste un codice qui per aiutarti, quindi rispondere alla domanda molto più funziona per noi.
Se vuoi prendere un file, hai bisogno di qualcosa del genere in un file html da qualche parte:
<form method="post" enctype="multipart/form-data">
<input type="file" name="myfile" />
<input type="submit" name="submit" value="Upload" />
</form>
Questo ti darà il pulsante Sfoglia, un pulsante di caricamento per avviare l'azione (inviare il modulo) e annotare il tipo in modo che Django sappia darti request.FILES
In una vista da qualche parte è possibile accedere al file con
def myview(request):
request.FILES['myfile'] # this is my file
C'è un'enorme quantità di informazioni nei documenti di caricamento dei file
Ti consiglio di leggere attentamente la pagina e iniziare a scrivere il codice , quindi tornare con esempi e impilare le tracce quando non funziona.
enctype="multipart/form-data"
cui avevo bisogno per farlo funzionare, grazie!
Guarda il repository github , funziona con Django 3
Esegui startproject ::
$ django-admin.py startproject sample
ora viene creata una cartella ( esempio ).
Crea un'app ::
$ cd sample
$ python manage.py startapp uploader
Ora uploader
viene creata una cartella ( ) con questi file:
uploader/
__init__.py
admin.py
app.py
models.py
tests.py
views.py
migrations/
__init__.py
Su sample/settings.py
add 'uploader'
a INSTALLED_APPS
e aggiungere MEDIA_ROOT
e MEDIA_URL
, cioè ::
INSTALLED_APPS = [
'uploader',
...<other apps>...
]
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
in sample/urls.py
aggiunta ::
...<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)
aggiornamento uploader/models.py
::
from django.db import models
class Upload(models.Model):
upload_file = models.FileField()
upload_date = models.DateTimeField(auto_now_add =True)
aggiornamento 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
Crea una cartella campione / uploader / template / uploader
Crea un file upload_form.html cioè 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>
Sincronizza database e ran server ::
$ python manage.py makemigrations
$ python manage.py migrate
$ python manage.py runserver
visita http: // localhost: 8000 /
FileField
po 'suhail ha usato ImageField
qualcuno, qualcuno potrebbe spiegare per favore le scelte?
FileField
. ImageField
è necessario solo per il caricamento di immagini. l'aggiornamento funzionerà con Django 1.11.
Devo dire che trovo confusa la documentazione su Django. Anche per l'esempio più semplice, perché vengono menzionati i moduli? L'esempio che ho avuto per lavorare in 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()
Il file html assomiglia al codice seguente, anche se questo esempio carica solo un file e il codice per salvare i file gestisce molti: -
<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>
Questi esempi non sono il mio codice, sono stati ottenuti da altri due esempi che ho trovato. Sono un principiante relativamente di Django, quindi è molto probabile che mi manchi qualche punto chiave.
FileField
e a model.Form
. Per i principianti (e per compiti banali), l'elaborazione manuale dei file caricati come mostrato sopra è meno confusa.
Avevo anche il requisito simile. La maggior parte degli esempi in rete chiedono di creare modelli e creare moduli che non volevo usare. Ecco il mio codice finale.
if request.method == 'POST':
file1 = request.FILES['file']
contentOfFile = file1.read()
if file1:
return render(request, 'blogapp/Statistics.html', {'file': file1, 'contentOfFile': contentOfFile})
E in HTML per caricare ho scritto:
{% 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 %}
Di seguito è riportato l'HTML che visualizza il contenuto del file:
{% block content %}
<h3>File uploaded successfully</h3>
{{file.name}}
</br>content = {{contentOfFile}}
{% endblock %}
Estendendo l'esempio di 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
Puoi chiamare questa handle_uploaded_file
funzione dalla tua vista con l'oggetto file caricato. Ciò salverà il file con un nome univoco (con prefisso con il nome del file caricato originale) nel filesystem e restituirà il percorso completo del file salvato. È possibile salvare il percorso nel database e fare qualcosa con il file in un secondo momento.
request.FILES['myfile']
) a handle_uploaded_file
, non lo request
stesso.
prefix=source.name
ha aggiunto caratteri extra alla fine del file, rovinando l'estensione del file. Ad esempio, è upload.csv
stato modificato in upload.csv5334
. Modificandolo per suffix=source.name
risolverlo per me.
Qui può esserti utile: crea un campo file nel tuo model.py
Per caricare il file (nel tuo 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)
e usa quel campo anche nel tuo modello.
Puoi fare riferimento agli esempi di server in Fine Uploader, che ha la versione di django. https://github.com/FineUploader/server-examples/tree/master/python/django-fine-uploader
È molto elegante e, soprattutto, offre funzionalità js lib. Il modello non è incluso negli esempi di server, ma puoi trovare la demo sul suo sito web. Uploader eccellente: http://fineuploader.com/demos.html
views.py
UploadView invia posta ed elimina la richiesta ai rispettivi gestori.
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)
Ho affrontato il problema simile e risolto dal sito di amministrazione di 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)