2009-10-26 13 views
7

Voy a ser honesto: esta es una pregunta que hice en la lista de correo de Django-Usuarios la semana pasada. Como todavía no recibí ninguna respuesta, la vuelvo a publicar en Stack Overflow con la esperanza de que reciba más atención aquí.Aplicación Django que puede proporcionar una funcionalidad de carga de archivos múltiples/masivos fácil de usar para otras aplicaciones

Quiero crear una aplicación que hace que sea fácil de hacer fácil de usar, cargar archivos múltiples/masivos en sus propias aplicaciones. Con fácil de usar, I significa subir como Gmail, Flickr, ... donde el usuario puede seleccionar múltiples archivos a la vez en el cuadro de diálogo de búsqueda de archivos. Luego, los archivos se cargan secuencialmente o en paralelo, y se muestra una buena descripción general de los archivos seleccionados en la página con una barra de progreso junto a ellos. Un botón de "Cancelar" cargar también es una opción posible.

Toda esa amabilidad generalmente se resuelve usando un objeto Flash. completas soluciones están ahí fuera para el lado del cliente, como: SWFUpload http://swfupload.org/, FancyUpload http://digitarald.de/project/fancyupload/ , YUI 2 Uploader http://developer.yahoo.com/yui/uploader/ y probablemente muchos más.

Por supuesto, el truco es obtener esas soluciones integradas en su proyecto . Especialmente en un marco como Django, el doble así que si quieres es reutilizable.

Tengo algunas ideas, pero no soy un experto en Django ni en las soluciones de carga basadas en Flash . Voy a compartir mis ideas aquí con la esperanza de obteniendo algunos comentarios de personas más conocedoras y con experiencia. (o incluso sólo algunos 'quiero esto también!' Respuestas :))

Usted notará que hago algunas suposiciones: esto es mantener el alcance (inicial) de la aplicación bajo control. Estos supuestos son de discutible supuesto:

bien, mi idea es hasta el momento:

  • Si desea múltiples archivos de carga masiva, usted va a tener un modelo para contener cada archivo en. Es decir el modelo contendrá un FileField o un ImageField. Modelos con cantidad múltiple (pero por supuesto finita) de FileFields/ ImageFields no necesitan una carga masiva fácil imho: si tienes un modelo con 100 FileFields estás haciendo algo mal :) Ejemplos en los que querrías mi tipo previsto de carga masiva:

    • una aplicación que tiene un solo modelo 'Folleto' con un campo de archivo, un campo título (creado de forma dinámica a partir del nombre de archivo) y un campo de DATE_ADDED.
    • Una aplicación de galería de fotos con los modelos 'Galería' y 'Foto'. Usted elige una galería para agregar imágenes a, cargar las imágenes y se crean nuevos objetos de fotos y claves foráneas establecidas en la Galería elegida.
  • Sería bueno para poder configurar o ampliar la aplicación de la solución de carga del flash favorito .Podemos elegir uno de los tres anteriores como de forma predeterminada, pero implementamos la aplicación para que las personas puedan agregar fácilmente implementaciones adicionales (algo así como que Django puede usar múltiples bases de datos ). Deje que sea agnóstico para cualquier solución particular del lado del cliente.

  • Si tenemos que elegir uno para empezar, ¿tal vez elegir el que tenga la huella más pequeña ? (descarga más pequeña de las cosas del lado del cliente)

  • Las soluciones basadas en Flash de forma asincrónica (y secuencialmente o en paralelo) ENVÍAN los archivos a una url. Sugiero que la URL sea local en nuestra aplicación genérica (por lo que es igual para cada aplicación en la que use nuestra aplicación ). Esa url irá a una vista proporcionada por nuestra aplicación genérica.

  • La vista hará lo siguiente: crear una nueva instancia de modelo, agregar el archivo , OPCIONALMENTE HACER EXTRA STUFF y guardar la instancia.

  • DO EXTRA STUFF es el código que la aplicación que utiliza nuestra aplicación desea ejecutar. No tiene que proporcionar ningún código adicional, si el modelo tiene solo un FileField/ImageField, el código de vista estándar hará el trabajo. Pero la mayoría aplicación va a querer hacer cosas extra que pienso, como llenar en los otros campos: título, DATE_ADDED, ForeignKeys, muchosamuchos, ...

  • que aún no han pensado en un mecanismo para hacer cosas EXTRA. Solo envolviendo la vista de la aplicación genérica vino a la mente, pero eso no es amigable para el desarrollador , ya que tendría que escribir su propio patrón de URL y su propia vista . Entonces tienes que decirle a las soluciones Flash que utilicen una nueva url etc ... Creo que algo como señales podrían usarse aquí?

  • Formas/Admin: sigo siendo muy superficiales sobre cómo todo esto podría ser mejor integrado en la administración o genérico formas Django/widgets/... (y esto es fuera mi falta de experiencia Django muestra) :

    • en el caso de la aplicación Galería/Foto: Usted puede proporcionar un widget de carga de fotos de masa en la Galería detalle la forma . Pero, ¿qué pasa si la instancia de la Galería aún no está guardada? La vista de carga del archivo no podrá establecer las claves externas en las instancias de Photo . Veo que la aplicación de autenticación, cuando crea un usuario, primero pregunta por nombre de usuario y contraseña y solo luego le proporciona un formulario más grande para completar emailadres, elegir roles, etc. Podríamos hacer algo como que.
    • En el caso de una aplicación con solo un modelo: ¿Cómo se proporciona un formulario en el administrador de Django para realizar su carga masiva ? No puede hacerlo con la forma de detalle de su modelo, que es solo para una instancia de modelo.

Probablemente hay docenas más preguntas que necesitan ser respondidas antes de incluso de que pueda comenzar en esta aplicación. Entonces por favor dime lo que piensas! Dar entrada! ¿Qué te gusta? Qué no? ¿Qué harías diferente? ¿Es esta idea sólida? ¿Dónde no está?

¡Gracias!

Respuesta

12

Acabo de lanzar una aplicación simple para esto hace aproximadamente un mes: django-uploadify.

Básicamente es una etiqueta de plantilla Django que actúa como un contenedor para la muy ingeniosa Uploadify (requiere jQuery). Su uso es tan simple como añadir esto a su plantilla ...

{% load uploadify_tags }{% multi_file_upload ‘/upload/complete/url/’ %} 

La etiqueta se activará eventos (1) por archivo, tanto en el lado del cliente y del lado del servidor (señal de Django) para indicar cuando un entrante archivo ha sido recibido

Por ejemplo, suponiendo que tiene un modelo de 'Medios' que se encarga de todos los archivos subidos por los usuarios ...

def upload_received_handler(sender, data, **kwargs): 
    if file: 
     new_media = Media.objects.create(
      file = data, 
      new_upload = True, 
     ) 
     new_media.save() 

upload_recieved.connect(upload_received_handler, dispatch_uid=‘whatever.upload_received’) 

Mira la wiki para obtener información sobre cómo configurarlo y crear los manejadores de señales (Servidor de cliente).


Acerca de su aplicación conceptual desde arriba, aquí hay un par de puntos de consideración:

  • Tener la aplicación crea automáticamente la instancia "Modelo del archivo" probablemente no es tan robusta como personas ya pueden tener su propios modelos que están trabajando con
  • Si desea implementar cualquier tipo de seguridad o autenticación, necesita un sistema abierto y menos de un tipo 'autocrear'
  • Realmente creo que las señales/eventos son la forma de manejar esto, y también ha en la parte 'HACER OTRA COSA' de lo que mencionas.
  • Mi conclusión fue que la carga múltiple nunca puede ser realmente un widget de formulario en el sentido de que Django implementa widgets de formulario. Lo más probable es que 1 archivo esté representado por 1 instancia de modelo (con algunas excepciones), lo que significa que terminamos con una situación en la que 1 widget puede representar N instancias de modelo. Sin embargo, Django está configurado para que un widget represente 1 valor para 1 campo en 1 instancia. Simplemente no cabe para la mayoría de los casos de uso tenerlo como un widget (de ahí por qué fui la ruta de la etiqueta de la plantilla).
+0

¡Eso se ve bastante increíble! Una pregunta sin embargo: ¿Puedo enviar información adicional con la carga del archivo? Por ejemplo, el PK de, digamos, la Galería, a la que pertenece la Foto. Si no puedo hacer eso, no puedo guardar el modelo en el momento en que recibo el archivo. Entonces tendría que permitir que el FK sea nulo y usar su método sugerido para distinguir entre archivos cargados recientemente. El problema que veo con ese método es que varios usuarios pueden estar cargando archivos de forma simultánea. Además: todavía no sabría a qué pertenece Galley the Photo (¿Tendría que hacer que el usuario elija uno después de la carga?) – hopla

+0

Acerca de mi implementación conceptual: no dejaría que la aplicación cree automáticamente una instancia de 'FileModel' pero de un modelo elegido por el programador (es decir, su propio Modelo). Sus otras observaciones son muy perspicaces, gracias. Además: dado que ya tienes algo que podría hacer lo que necesito, ahora estoy más inclinado a hackear eso :) – hopla

+0

El patrón que funcionaría mejor con la aplicación es "Cargar primero, hacer preguntas en segundo lugar". Si alguna vez has usado Flickr, has visto esto en acción. Los modelos de medios tienen 2 campos "new_upload" (bool) y "uploaded_by" (FK al usuario). Ambos valores se establecen cuando el archivo se carga. En el lado del cliente, la URL a la que se envía al usuario una vez completadas las cargas (lo que se pasa a través de la etiqueta de plantilla) las lleva a una pantalla que muestra los archivos recién subidos y les permite elegir una galería (o etiqueta, o recortar, o lo que sea) cada archivo individualmente. –

Cuestiones relacionadas