Respuestas:
Uf, la documentación de Django realmente no tiene un buen ejemplo al respecto. Pasé más de 2 horas para desenterrar todas las piezas para entender cómo funciona esto. Con ese conocimiento, implementé un proyecto que hace posible cargar archivos y mostrarlos como una lista. Para descargar el código fuente del proyecto, visite https://github.com/axelpale/minimal-django-file-upload-example o clónelo:
> git clone https://github.com/axelpale/minimal-django-file-upload-example.git
Actualización 2013-01-30: La fuente en GitHub también tiene implementación para Django 1.4 además de 1.3. Aunque hay pocos cambios, el siguiente tutorial también es útil para 1.4.
Actualización 2013-05-10: Implementación para Django 1.5 en GitHub. Cambios menores en la redirección en urls.py y el uso de la etiqueta de plantilla de url en list.html. Gracias a Hubert3 por el esfuerzo.
Actualización 2013-12-07: Django 1.6 compatible en GitHub. Una importación cambió en myapp / urls.py. Gracias a Arthedian .
Actualización 2015-03-17: Django 1.7 compatible con GitHub, gracias a aronysidoro .
Actualización 2015-09-04: Django 1.8 compatible con GitHub, gracias a nerogit .
Actualización 2016-07-03: Django 1.9 compatible con GitHub, gracias a daavve y nerogit
Un proyecto básico de Django 1.3 con una sola aplicación y directorio media / para cargas.
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
Para cargar y servir archivos, debe especificar dónde almacena Django los archivos cargados y desde qué URL Django los sirve. MEDIA_ROOT y MEDIA_URL están en settings.py de forma predeterminada pero están vacías. Vea las primeras líneas en Django Managing Files para más detalles. Recuerde también configurar la base de datos y agregar 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',
)
A continuación, necesita un modelo con un FileField. Este campo particular almacena archivos, por ejemplo, en medios / documentos / 2011/12/24 / según la fecha actual y MEDIA_ROOT. Consulte la referencia de FileField .
# -*- coding: utf-8 -*-
from django.db import models
class Document(models.Model):
docfile = models.FileField(upload_to='documents/%Y/%m/%d')
Para manejar bien la carga, necesita un formulario. Este formulario tiene solo un campo, pero eso es suficiente. Consulte la referencia del formulario FileField para obtener más detalles.
# -*- 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 donde sucede toda la magia. Presta atención como request.FILES
se manejan. Para mí, fue realmente difícil detectar el hecho de que request.FILES['docfile']
se puede guardar en modelos. FileField así como así. Save () del modelo maneja el almacenamiento del archivo en el sistema de archivos automáticamente.
# -*- 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 no sirve MEDIA_ROOT de forma predeterminada. Eso sería peligroso en el entorno de producción. Pero en la etapa de desarrollo, podríamos acortarnos. Presta atención a la última línea. Esa línea permite que Django sirva archivos de MEDIA_URL. Esto funciona solo en la etapa de desarrollo.
Consulte la referencia de django.conf.urls.static.static para obtener más detalles. Consulte también esta discusión sobre la publicación de archivos multimedia .
# -*- 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)
Para que la vista sea accesible, debe especificar sus URL. Nada especial aquí.
# -*- coding: utf-8 -*-
from django.conf.urls import patterns, url
urlpatterns = patterns('myapp.views',
url(r'^list/$', 'list', name='list'),
)
La última parte: plantilla para la lista y el formulario de carga debajo de ella. El formulario debe tener el atributo enctype establecido en "multipart / form-data" y el método establecido en "post" para hacer posible la carga en Django. Consulte la documentación de Carga de archivos para más detalles.
FileField tiene muchos atributos que se pueden usar en plantillas. Por ejemplo, {{document.docfile.url}} y {{document.docfile.name}} como en la plantilla. Vea más sobre esto en el artículo Uso de archivos en modelos y en la documentación del objeto El archivo .
<!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>
Simplemente ejecute syncdb y runserver.
> cd myproject
> python manage.py syncdb
> python manage.py runserver
Finalmente, todo está listo. En el entorno de desarrollo predeterminado de Django, se puede ver la lista de documentos cargados en localhost:8000/list/
. Hoy los archivos se cargan en / path / to / myproject / media / documents / 2011/12/17 / y se pueden abrir desde la lista.
Espero que esta respuesta ayude a alguien tanto como me hubiera ayudado.
{% url list %}
convierte {% url "list" %}
.
En términos generales, cuando está tratando de "obtener un ejemplo de trabajo", es mejor "comenzar a escribir código". No hay un código aquí para ayudarlo, por lo que hacer que responder la pregunta sea mucho más útil para nosotros.
Si desea obtener un archivo, necesita algo como esto en un archivo html en algún lugar:
<form method="post" enctype="multipart/form-data">
<input type="file" name="myfile" />
<input type="submit" name="submit" value="Upload" />
</form>
Eso le dará el botón de exploración, un botón de carga para iniciar la acción (enviar el formulario) y anotar el enctype para que Django sepa darle request.FILES
En una vista en algún lugar, puede acceder al archivo con
def myview(request):
request.FILES['myfile'] # this is my file
Hay una gran cantidad de información en los documentos de carga de archivos
Le recomiendo que lea la página a fondo y simplemente comience a escribir código , luego regrese con ejemplos y seguimientos de pila cuando no funcione.
enctype="multipart/form-data"
que necesitaba para que esto funcionara, ¡gracias!
Vea el repositorio de github , funciona con Django 3
Ejecute startproject ::
$ django-admin.py startproject sample
ahora una carpeta ( se crea muestra ).
Crea una aplicación ::
$ cd sample
$ python manage.py startapp uploader
Ahora uploader
se crea una carpeta ( ) con estos archivos ::
uploader/
__init__.py
admin.py
app.py
models.py
tests.py
views.py
migrations/
__init__.py
En sample/settings.py
agregar 'uploader'
a INSTALLED_APPS
y agregar MEDIA_ROOT
y MEDIA_URL
, es decir:
INSTALLED_APPS = [
'uploader',
...<other apps>...
]
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
en sample/urls.py
agregar ::
...<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)
actualización uploader/models.py
::
from django.db import models
class Upload(models.Model):
upload_file = models.FileField()
upload_date = models.DateTimeField(auto_now_add =True)
actualización 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
Crear una carpeta de muestra / cargador / plantillas / cargador
Cree un archivo upload_form.html, es decir 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>
Sincronice la base de datos y el servidor de ejecución ::
$ python manage.py makemigrations
$ python manage.py migrate
$ python manage.py runserver
visite http: // localhost: 8000 /
FileField
tiempo, suhail usó un ImageField
, ¿alguien podría explicar las opciones?
FileField
. ImageField
debe para cargar solo la imagen. la actualización funcionará con Django 1.11.
Debo decir que encuentro la documentación en django confusa. También para el ejemplo más simple, ¿por qué se mencionan los formularios? El ejemplo que puse a trabajar en views.py es: -
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()
El archivo html se parece al siguiente código, aunque este ejemplo solo carga un archivo y el código para guardar los archivos maneja muchos:
<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>
Estos ejemplos no son mi código, se obtuvieron de otros dos ejemplos que encontré. Soy un principiante relativo a django, por lo que es muy probable que me falte algún punto clave.
FileField
a model.Form
. Para principiantes (y para tareas triviales), el procesamiento manual de los archivos cargados como se muestra arriba es menos confuso.
También tuve el requisito similar. La mayoría de los ejemplos en la red piden crear modelos y crear formularios que no quería usar. Aquí está mi código final.
if request.method == 'POST':
file1 = request.FILES['file']
contentOfFile = file1.read()
if file1:
return render(request, 'blogapp/Statistics.html', {'file': file1, 'contentOfFile': contentOfFile})
Y en HTML para subir escribí:
{% 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 %}
El siguiente es el HTML que muestra el contenido del archivo:
{% block content %}
<h3>File uploaded successfully</h3>
{{file.name}}
</br>content = {{contentOfFile}}
{% endblock %}
Ampliando el ejemplo de 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
Puede llamar a esta handle_uploaded_file
función desde su vista con el objeto de archivo cargado. Esto guardará el archivo con un nombre único (prefijado con el nombre del archivo original cargado) en el sistema de archivos y devolverá la ruta completa del archivo guardado. Puede guardar la ruta en la base de datos y hacer algo con el archivo más adelante.
request.FILES['myfile']
) a handle_uploaded_file
, no el request
propio.
prefix=source.name
se agregaron caracteres adicionales al final del archivo y se confundió con la extensión del archivo. Por ejemplo, upload.csv
se cambió a upload.csv5334
. Cambiándolo a suffix=source.name
arreglado para mí.
Aquí puede ayudarte: crea un campo de archivo en tu models.py
Para cargar el archivo (en su 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)
y usa ese campo en tu plantilla también.
Puede consultar ejemplos de servidores en Fine Uploader, que tiene la versión django. https://github.com/FineUploader/server-examples/tree/master/python/django-fine-uploader
Es muy elegante y lo más importante de todo, proporciona js lib destacada. La plantilla no está incluida en los ejemplos de servidores, pero puede encontrar la demostración en su sitio web. Cargador fino: http://fineuploader.com/demos.html
views.py
UploadView despacha la solicitud de publicación y eliminación a los respectivos controladores
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'
}))
formas.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)
Me enfrenté al problema similar y lo resolví con el sitio de administración 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)