2009-07-27 23 views
121

Estoy tratando de configurar mis cargas para que si el usuario joe carga un archivo va a MEDIA_ROOT/joe en lugar de tener todos los archivos a MEDIA_ROOT. El problema es que no sé cómo definir esto en el modelo. Así es como se ve actualmente:Django FileField con upload_to determinado en el tiempo de ejecución

class Content(models.Model): 
    name = models.CharField(max_length=200) 
    user = models.ForeignKey(User) 
    file = models.FileField(upload_to='.') 

Lo que quiero es en lugar de '.' como upload_to, tiene que ser el nombre del usuario.

Entiendo que a partir de Django 1.0 puedes definir tu propia función para manejar el upload_to pero esa función tampoco tiene idea de quién será el usuario, así que estoy un poco perdido.

¡Gracias por la ayuda!

Respuesta

242

Usted probablemente ha leído the documentation, así que aquí está un ejemplo fácil de hacer que tenga sentido:

def content_file_name(instance, filename): 
    return '/'.join(['content', instance.user.username, filename]) 

class Content(models.Model): 
    name = models.CharField(max_length=200) 
    user = models.ForeignKey(User) 
    file = models.FileField(upload_to=content_file_name) 

Como se puede ver, ni siquiera es necesario utilizar el nombre de archivo dado - se puede anular ese en su upload_to invocable también si le gustó.

+0

Sí, probablemente pertenece a documentos - es un FAQ bastante razonable en IRC – SmileyChris

+2

¿Funciona esto con ModelForm? Puedo ver que la instancia tiene todos los atributos del modelo de clase, pero no hay valores (solo un str del nombre del campo). En la plantilla, el usuario está oculto. Puede que tenga que enviar una pregunta, he estado buscando en Google durante horas. – mgag

+0

Sí, funciona, y sí, debe hacer una nueva pregunta (o pedir ayuda sobre #django irc) – SmileyChris

11

Esto realmente ayudó. Por el amor un poco más de la brevedad, decidido utilizar lambda en mi caso:

file = models.FileField(
    upload_to=lambda instance, filename: '/'.join(['mymodel', str(instance.pk), filename]), 
) 
+2

Esto no funcionó para mí en Django 1.7 usando migraciones.Terminó creando una función y la migración tomó. – aboutaaron

+0

Incluso si no puede hacer que lambda trabaje usando str (instance.pk) es una buena idea si tiene problemas con la sobrescritura de archivos cuando no lo desea. –

+0

instancia no tiene un 'pk' antes de guardar. Solo funciona para actualizaciones, no creaciones (inserciones). –

3

Una nota sobre el uso del valor pk 'ejemplo' de objeto. De acuerdo con la documentación:

En la mayoría de los casos, este objeto no se habrá guardado en la base de datos, sin embargo, lo que si se utiliza el valor predeterminado AutoField, todavía no puede tener un valor por su campo de clave principal.

Por lo tanto, la validez del uso de pk depende de cómo se defina su modelo en particular.

+0

Tengo None como valor. No puedo encontrar la manera de solucionarlo. ¿Puedes explicarlo con un poco de detalle? –

Cuestiones relacionadas