50 votes

Chemin de fichier dynamique dans Django

Je suis en train de créer des chemins d'accès aux fichiers dans django. Je veux faire un système de fichiers comme ceci:

 -- user_12
     --- photo_1
     --- photo_2
 --- user_ 13
     ---- photo_1

J'ai trouvé une question connexe : Django image Personnalisée télécharger le terrain avec chemin dynamique

Ici, ils disent que nous pouvons changer le upload_to chemin et conduit à http://docs.djangoproject.com/en/1.2/topics/files/ doc. Dans la documentation, il est un exemple :

from django.db import models
from django.core.files.storage import FileSystemStorage

    fs = FileSystemStorage(location='/media/photos')

    class Car(models.Model):
        ...
        photo = models.ImageField(storage=fs)

Mais, ce n'est pas encore dynamique, je veux donner des de Voiture id pour le nom de l'image, et je ne peux pas attribuer l'id de Voiture avant la définition de terminé. Alors, comment puis-je créer un chemin d'accès avec la voiture ID ??

83voto

DrMeers Points 1805

Vous pouvez utiliser un appelable dans l' upload_to argument plutôt que d'utiliser de rangement sur mesure. Voir les docs, et notez l'avertissement que la clé primaire ne peut pas encore être fixée lorsque la fonction est appelée (parce que le téléchargement peut être traitée avant que l'objet est enregistré dans la base de données), donc à l'aide d' ID pourrait ne pas être possible. Vous pourriez wan envisager d'utiliser un autre champ du modèle, tels que les limaces. E. g:

import os
def get_upload_path(instance, filename):
    return os.path.join(
      "user_%d" % instance.owner.id, "car_%s" % instance.slug, filename)

alors:

photo = models.ImageField(upload_to=get_upload_path)

6voto

Yuji 'Tomita' Tomita Points 46106

http://docs.djangoproject.com/en/1.2/ref/models/fields/#django.db.models.FileField.upload_to

def upload_path_handler(instance, filename):
    return "user_{id}/{file}".format(id=instance.user.id, file=filename)

class Car(models.Model):
    ...
    photo = models.ImageField(upload_to=upload_path_handler, storage=fs)

Il y a un avertissement dans les docs, mais il ne devrait pas vous affecter puisque nous sommes après l' User ID et pas l' Car ID.

Dans la plupart des cas, cet objet ne sera pas ont été enregistrées dans la base de données, donc, si on utilise la valeur par défaut AutoField, il pourrait ne pas encore avoir de la valeur pour ses champ de clé primaire.

6voto

James Lin Points 2721

Vous pouvez utiliser la fonction lambda comme ci-dessous, notez que si l'instance est nouvelle, elle n'aura pas l'ID d'instance, alors utilisez autre chose:

 logo = models.ImageField(upload_to=lambda instance, filename: 'directory/images/{0}/{1}'.format(instance.owner.id, filename))
 

0voto

Laur Ivan Points 1786

Ce gars a un moyen de faire un chemin dynamique. L'idée est de définir votre stockage préféré et de personnaliser le paramètre "upload_to ()" avec une fonction.

J'espère que cela t'aides.

0voto

balazs Points 2041

J'ai trouvé une autre solution, qui est sale, mais ça fonctionne. Vous devez créer un nouveau mannequin modèle, qui est synchronisé avec celui d'origine. Je ne suis pas fier de cela, mais n'a pas trouvé une autre solution. Dans mon cas, je veux télécharger des fichiers, et de les stocker chacun dans un répertoire nommé d'après l'id de modèle (parce que je vais générer il y a plus de fichiers).

l'model.py

class dummyexperiment(models.Model):
  def __unicode__(self):
    return str(self.id)

class experiment(models.Model):
  def get_exfile_path(instance, filename):
    if instance.id == None:
      iid = instance.dummye.id
    else:
      iid = instance.id
    return os.path.join('experiments', str(iid), filename)

  exfile = models.FileField(upload_to=get_exfile_path)

  def save(self, *args, **kwargs):
    if self.id == None:
      self.dummye = dummyexperiment()
      self.dummye.save()
    super(experiment, self).save(*args, **kwargs)

Je suis très nouveau en python et django, mais cela me semble ok pour moi.

une autre solution:

def get_theme_path(instance, filename):
  id = instance.id
  if id == None:
    id = max(map(lambda a:a.id,Theme.objects.all())) + 1
  return os.path.join('experiments', str(id), filename)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X