web-dev-qa-db-fra.com

Définir le champ de fichier de Django sur un fichier existant

J'ai un fichier existant sur le disque (par exemple, /folder/file.txt) et un champ de modèle FileField dans Django.

Quand je fais 

instance.field = File(file('/folder/file.txt'))
instance.save()

il ré-enregistre le fichier en tant que file_1.txt (la prochaine fois que ce sera _2, etc.).

Je comprends pourquoi, mais je ne veux pas ce comportement - je sais que le fichier auquel je souhaite associer le champ est vraiment là, et je veux juste que Django le pointe du doigt.

Comment?

72
Guard

Si vous voulez le faire de manière permanente, vous devez créer votre propre classe FileStorage.

import os
from Django.conf import settings
from Django.core.files.storage import FileSystemStorage

class MyFileStorage(FileSystemStorage):

    # This method is actually defined in Storage
    def get_available_name(self, name):
        if self.exists(name):
            os.remove(os.path.join(settings.MEDIA_ROOT, name))
        return name # simply returns the name passed

Maintenant, dans votre modèle, vous utilisez votre MyFileStorage modifié

from mystuff.customs import MyFileStorage

mfs = MyFileStorage()

class SomeModel(model.Model):
   my_file = model.FileField(storage=mfs)
18
Burhan Khalid

il suffit de définir instance.field.name sur le chemin de votre fichier

par exemple.

class Document(models.Model):
    file = FileField(upload_to=get_document_path)
    description = CharField(max_length=100)


doc = Document()
doc.file.name = 'path/to/file'  # must be relative to MEDIA_ROOT
doc.file
<FieldFile: path/to/file>
97
bara

essayez ceci ( doc ):

instance.field.name = <PATH RELATIVE TO MEDIA_ROOT> 
instance.save()
8
uNmAnNeR

C'est juste d'écrire sa propre classe de stockage. Cependant, get_available_name n'est pas la bonne méthode à remplacer.

get_available_name est appelé lorsque Django voit un fichier portant le même nom et tente d'obtenir un nouveau nom de fichier disponible. Ce n'est pas la méthode qui provoque le changement de nom. la méthode qui a provoqué est _save. Les commentaires dans _save sont plutôt bons et vous pouvez facilement le trouver. Ce fichier ouvre l'écriture avec l'indicateur os.O_EXCL qui génère une erreur OSError si le même nom de fichier existe déjà. Django attrape cette erreur puis appelle get_available_name pour obtenir un nouveau nom.

Donc, je pense que la bonne façon est de remplacer _save et d'appeler os.open () sans l'indicateur os.O_EXCL. La modification est assez simple mais la méthode est un peu longue, donc je ne la colle pas ici. Dis-moi si tu as besoin de plus d'aide :)

4
x1a0

J'ai eu exactement le même problème! alors je me rends compte que mes modèles causaient ça. Par exemple, j'ai mes modèles comme ceci:

class Tile(models.Model):
  image = models.ImageField()

Ensuite, je voulais avoir plus d'une tuile référençant le même fichier sur le disque! La façon dont j'ai trouvé pour résoudre cela a été de changer la structure de mon modèle en ceci:

class Tile(models.Model):
  image = models.ForeignKey(TileImage)

class TileImage(models.Model):
  image = models.ImageField()

Ce qui après, je réalise que cela a plus de sens, parce que si je veux que le même fichier soit sauvegardé plus d'un fichier dans ma base de données, je dois créer un autre tableau pour cela! 

Je suppose que vous pouvez également résoudre votre problème de cette manière, en espérant simplement pouvoir changer de modèle! 

MODIFIER

Aussi, je suppose que vous pouvez utiliser un stockage différent, comme par exemple: SymlinkOrCopyStorage

http://code.welldev.org/Django-storages/src/11bef0c2a410/storages/backends/symlinkorcopy.py

0
Arthur Neves