Django file upload

Some interesting examples on how to handle file uploads using Django:

  • Code snippet posted on Djangosnippets. The file is saved by declaring a save() method in the form class. This method is invoked when calling form.save(), which is standard Django newforms practice. (Note that this snipped uses clean_data. As of Django version 0.96, clean_data has been renamed to cleaned_data, so you will have to change the code or it won’t work)
  • Django image upload and validation. The author uses a model for the file and its related data. The uploaded file is saved by calling the save_FOO_file method. (This method is automatically provided by Django for fields declared as models.ImageField or models.FileField in the model. See the db-api documentation.)
  • Django image upload, form_for_instance and monkey-patching. The example code creates a form class from request.user by calling form_for_instance. The resulting class in then monkey-patched to insert the avatar image validation code. (Although the code is interesting the monkey patch seems unnecessary. I wouldn’t mind inserting the avatar validation method in a UserProfileForm class derived from form.Forms. The code would be certainly clearer: I think KISS takes precedence over DRY in this case.)

Interesting, there seems to be no easy way of limiting the uploaded file size. The file can be rejected at validation time, but the data would have already been transfered.

A file upload recipe

After reading those posts, I think that a good recipe for handling file uploads in Django would be:

  • Write a django model for the uploaded file and its related data. Using a Django model makes sense, because it is usually necessary for the application to keep track of the uploaded files.
  • Write a subclass of form.Forms and declare a clean_FOO method for each models.FileInput or models.ImageInput fields declared in the model class. These clean_FOO methods are used to validate the uploaded files.
  • use a django view to receive the POST data, or display the form if no data is posted or errors are found.
  • validate the uploaded file or files by triggering the standard django newforms validation mechanism: is_valid().
  • save the file or files getting the data directly from the request.FILES object, by writing a save() method for the subclassed form or by calling save_FOO_file for the model instance.

A simpler way to upload a file

The following short Django example uses no data models, does no data validation, and saves the file directly to disk using python standard file functions. It is just a simple test I wrote to get familiar with the request.FILES object. This is not production code: it could be used to execute an arbitrary script on the server.
The directory where the file is to be saved must be writable by the user that is running the Django server script. (The example uses MEDIA_ROOT as defined in settings.py.)

file: views.py

file: fileupload.html


Comments (10)

Django newforms documentation updated

The Django newforms documentation has been updated some days ago. It includes an explanation on how to use form_for_models and form_for_instance and provides some examples.

More interesting, however, is when not to use them: “If you want to create a form whose fields map to more than one model, or a form that contains fields that aren’t on a model, you shouldn’t use these shortcuts.”


Leave a Comment

Aprendiendo Lisp

Desde hace algunas semanas estoy aprendiendo Lisp. Estoy bien cómodo programando en Python, y he aprendido bastante dando clases de Java. Pero Lisp tiene algunas cosas que no tienen esos lenguajes (y ningún otro, al parecer), y que me interesa aprender, en particular la capacidad de extender la sintaxis del lenguaje como práctica habitual de programación. Esto en Lisp se llama Macros, y no tienen nada que ver con los macros como se entienden en C/C++. Como siempre, hay que sacar tiempo de donde no hay, así que estoy yendo más lento de lo que quisiera.

Los ensayos de Paul Graham son muy buenos y sugerentes, y el libro Hackers and Painters tampoco tiene pierde. Obviamente no quiere decir que coincida 100% con lo que dice, pero habla bastante de Lisp, por no decir que está absolutamente entusiasmado con Lisp.

Estoy usando dos libros: Practical Common Lisp, de Peter Siebel, que se puede descargar sin costo del website de APress. Y ANSI Common Lisp, de Paul Graham, que compré en Amazon.

Menos bla,bla,bla, quiero empezar a escribir programas…

Primera tarea, instalar alguna versión de lisp en la computadora. En Ubuntu:

Ya tenemos lisp en la computadora. Ahora basta escribir:

Common Lisp Linux

Practical Common Lisp recomienda usar Emacs como editor de texto/entorno de desarrollo y la extensión SLIME (Superior Lisp Interaction Mode for Emacs). (Más información sobre Emacs, ver Wikipedia.) Por ahora voy a seguir los consejos del libro, así que a instalar Emacs y Slime.

Intenté usar la versión de Emacs que está en los repositorios de Ubuntu, y que se integra con Gnome. Pero las letras en la pantalla se veían francamente horribles. Creo que la pantalla del Macro Assembler que tenía en la Atari 800XL que usaba en el siglo 20 se veía mejor. Bien, siempre hay soluciones. Buscando en Google “pretty emacs”, encontré esta página, donde se explica cómo instalar una versión de Emacs más reciente, compilada para que haga un render decente de los fonts. En la imagen se puede ver el resultado.

Emacs pretty fonts thumb

Segundo paso, aprender lo suficiente de Emacs como para crear un programa, guardarlo en un archivo y compilarlo. Emacs tiene fama de ser poco amigable, y lo es. En este post Erik Rasmussen explica con gracia cómo al comienzo no se explicaba por qué si Lisp es un lenguaje superior e increíble, es tan poco usado. Al menos eso es lo que se preguntaba él hasta que intentó usar Emacs.

El némesis de Emacs es vim, otro editor muy común en Linux. vim es poderoso. He desarrollado websites enteros usando vim. Incluso cuando estoy usando un procesador de texto me sorprendo a veces teclando “:w”, que es el comando de vim para guardar el archivo. Pero la verdad que entre perder tiempo tratando de que Lisp y vim se entendieran, preferí dedicar veinte minutos a seguir el tutorial de que trae el mismo Emacs. (Se accede al tutorial presionando Ctrl-h t. O, como dicen en Emacs, C-h t.) Y confirmado: veinte minutos bastan para empezar y moverse en Emacs.

Uno de los comentarios del post de Rasmussen dice que hay un plugin de lisp para Eclipse: más adelante le daremos una oportunidad.

Tercer y último paso, instalar SLIME. Slime es un entorno de desarrollo para programar en Lisp dentro de Emacs. En Ubuntu se puede instalar escribiendo:

Como se explica aquí, también es necesario añadir lo siguiente al archivo ~/.emacs:

Listo. Ahora sí, en Emacs: M-x slime, y aparece SLIME.

SLIME

Y podemos escribir: (hello-world).


Comments (4)