Pregunta Necesita un ejemplo mínimo de carga de archivos de Django [cerrado]


Como novato de Django, tengo dificultades para crear una aplicación de carga en Django 1.3. No pude encontrar ningún ejemplo / fragmento actualizado. ¿Puede alguien publicar un código de ejemplo mínimo pero completo (Modelo, Vista, Plantilla) para hacerlo?


583
2018-05-03 15:17


origen


Respuestas:


Uff, la documentación de Django realmente no tiene un buen ejemplo sobre esto. 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 la fuente del proyecto, visite https://github.com/axelpale/minimal-django-file-upload-example o clonarlo:

> 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 es compatible con GitHub. Una importación cambió en myapp / urls.py. Gracias va a Arthedian.

Actualización 2015-03-17: Django 1.7 con soporte en GitHub, gracias a aronysidoro.

Actualización 2015-09-04: Django 1.8 con soporte en GitHub, gracias a nerogit.

Actualización 2016-07-03: Django 1.9 con soporte en GitHub, gracias a daavve y nerogit

Árbol de proyecto

Un proyecto básico de Django 1.3 con una sola aplicación y medios / directorio 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

1. Configuraciones: myproject / settings.py

Para cargar y servir archivos, debe especificar dónde almacena Django los archivos cargados y de qué URL los sirve. MEDIA_ROOT y MEDIA_URL están en settings.py de forma predeterminada, pero están vacíos. Ver las primeras líneas en Django Gestionando archivos para 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',
)

2. Modelo: myproject / myapp / models.py

Luego necesitas un modelo con un FileField. Este campo particular almacena archivos, p. a media / documents / 2011/12/24 / basado en la fecha actual y MEDIA_ROOT. Ver Referencia de FileField.

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

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

3. Forma: myproject / myapp / forms.py

Para manejar la carga, necesita un formulario. Esta forma tiene solo un campo, pero eso es suficiente. Ver Formulario FileField de referencia para detalles.

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

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

4. Ver: myproject / myapp / views.py

Una vista donde sucede toda la magia. Presta atención cómo request.FILES son manejados. Para mí, fue realmente difícil detectar el hecho de que request.FILES['docfile'] se puede guardar en modelos. FileField así como así. El 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)
    )

5. URL del proyecto: myproject / urls.py

Django no sirve MEDIA_ROOT de manera predeterminada. Eso sería peligroso en el entorno de producción. Pero en la etapa de desarrollo, podríamos acortar. Presta atención a la última línea. Esa línea permite a Django servir archivos de MEDIA_URL. Esto funciona solo en la etapa de desarrollo.

Ver django.conf.urls.static.static reference para detalles. Ver también esta discusión sobre servir 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)

6. URL de la aplicación: myproject / myapp / urls.py

Para hacer que la vista sea accesible, debe especificar urls para ello. Nada especial aquí.

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

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

7. Plantilla: myproject / myapp / templates / myapp / list.html

La última parte: plantilla para la lista y el formulario de carga debajo de ella. El formulario debe tener enctype-attribute establecido en "multipart / form-data" y el método establecido en "post" para posibilitar la carga a Django. Ver Documentación de carga de archivos para detalles.

FileField tiene muchos atributos que se pueden usar en plantillas. P.ej. {{document.docfile.url}} y {{document.docfile.name}} como en la plantilla. Ver más sobre estos en Usar archivos en el artículo de modelos y La documentación del objeto 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> 

8. Inicializar

Simplemente ejecuta syncdb y runserver.

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

Resultados

Finalmente, todo está listo. En el entorno de desarrollo predeterminado de Django, la lista de documentos cargados se puede ver en localhost:8000/list/. Hoy los archivos se cargan en / ruta / a / 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.


1196
2017-12-17 01:59



En términos generales, cuando intenta 'simplemente obtener un ejemplo de trabajo', es mejor 'comenzar a escribir el código'. No hay un código aquí para ayudarlo, por lo que hace que responder a la pregunta sea mucho más útil para nosotros.

Si quiere tomar un archivo, necesita algo como esto en un archivo html en alguna parte:

<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 Examinar, un botón de carga para iniciar la acción (envíe el formulario) y anote el enctype para que Django sepa que debe 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 el archivos de carga de documentos

Te recomiendo que leas la página a fondo y solo comienza a escribir el código - luego regrese con ejemplos y apile los rastros cuando no funcione.


57
2018-05-03 15:25



Manifestación

Actualización de La respuesta de Akseli Palén. ver el github repo, funciona con Django 2

Un ejemplo mínimo de carga de archivos de Django

1. Crea un proyecto django

Ejecute startproject ::

$ django-admin.py startproject sample

ahora una carpeta (muestra) es creado::

sample/
  manage.py
  sample/
    __init__.py
    settings.py
    urls.py
    wsgi.py 

2. crea una aplicación

Crea una aplicación ::

$ cd sample
$ python manage.py startapp uploader

Ahora una carpeta (uploader) con estos archivos se crean ::

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

3. Actualice settings.py

En sample/settings.py añadir 'uploader.apps.UploaderConfig' a INSTALLED_APPS y añadir MEDIA_ROOT y MEDIA_URL, es decir ::

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

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

4. Actualiza urls.py

en sample/urls.py añadir::

...<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.home, name='imageupload'),
]+ static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

5. Actualizar models.py

actualizar uploader/models.py::

from django.db import models
from django.forms import ModelForm

class Upload(models.Model):
    pic = models.FileField(upload_to="images/")    
    upload_date=models.DateTimeField(auto_now_add =True)

# FileUpload form class.
class UploadForm(ModelForm):
    class Meta:
        model = Upload
        fields = ('pic',)

6. Actualiza views.py

actualizar uploader/views.py::

from django.shortcuts import render
from uploader.models import UploadForm,Upload
from django.http import HttpResponseRedirect
from django.urls import reverse
# Create your views here.
def home(request):
    if request.method=="POST":
        img = UploadForm(request.POST, request.FILES)       
        if img.is_valid():
            img.save()  
            return HttpResponseRedirect(reverse('imageupload'))
    else:
        img=UploadForm()
    images=Upload.objects.all().order_by('-upload_date')
    return render(request,'home.html',{'form':img,'images':images})

7. crea plantillas

Crea una carpeta plantillas en la carpeta cargador, luego crea un archivo home.html, es decir, sample/uploader/templates/home.html::

<div style="padding:40px;margin:40px;border:1px solid #ccc">
    <h1>picture</h1>
    <form action="#" method="post" enctype="multipart/form-data">
        {% csrf_token %} {{form}} 
        <input type="submit" value="Upload" />
    </form>
    {% for img in images %}
        {{forloop.counter}}.<a href="{{ img.pic.url }}">{{ img.pic.name }}</a>
        ({{img.upload_date}})<hr />
    {% endfor %}
</div>

8. Sincronizar la base de datos

Sincronizar la base de datos y el servidor de ejecución ::

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

visitar http://localhost.com:8000


51
2018-06-05 17:10



Debo decir que la documentación de django me resulta confusa. También para el ejemplo más simple, ¿por qué se mencionan los formularios? El ejemplo que tengo para 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 código siguiente, 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 han obtenido de otros dos ejemplos que encontré. Soy relativamente principiante con Django, por lo que es muy probable que me falte algún punto clave.


22
2018-06-07 12:11



Extendiéndose en 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

Puedes llamar esto handle_uploaded_file función desde su vista con el objeto de archivo cargado. Esto guardará el archivo con un nombre único (con el prefijo del 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.


14
2018-05-03 15:42



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.


10
2017-10-20 10:39



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 %}

Lo siguiente es el HTML que muestra el contenido del archivo:

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

9
2017-11-10 02:16



Puede consultar los ejemplos del servidor 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 presentado. La plantilla no está incluida en los ejemplos de servidor, pero puede encontrar una demostración en su sitio web. Uploader bien: http://fineuploader.com/demos.html

django-fine-uploader

views.py

UploadView distribuye la publicación y la solicitud de eliminación a los controladores respectivos.

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)

9
2018-04-07 04:35



No estoy seguro de si hay desventajas para este enfoque, pero aún más mínimo, en views.py:

entry = form.save()

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

5
2018-05-19 13:00



Enfrenté el problema similar y lo solucioné en 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)

0
2018-05-14 06:58