J'ai un fichier existant sur le disque (disons /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 sous file_1.txt
(la prochaine fois _2
, etc.).
Je comprends pourquoi, mais je ne veux pas de ce comportement - je sais que le fichier auquel je veux associer le champ m'attend vraiment, et je veux juste que Django le pointe.
Comment?
FileField
. Chaque fois que aFileField
est enregistré, une nouvelle copie du fichier est créée. Il serait assez simple d'ajouter une option pour éviter cela.Réponses:
Si vous souhaitez 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)
la source
FilePathField
ou simplement en texte brut.il suffit de définir
instance.field.name
le chemin de votre fichierpar 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>
la source
MEDIA_ROOT
, c'est-à-dire.doc.file = 'path/to/file'
essayez ceci ( doc ):
la source
Il est juste d'écrire sa propre classe de stockage. Cependant, ce
get_available_name
n'est pas la bonne méthode pour remplacer.get_available_name
est appelé lorsque Django voit un fichier avec 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 causée est_save
. Les commentaires dans_save
sont assez bons et vous pouvez facilement trouver qu'il ouvre le fichier pour l'écriture avec un drapeauos.O_EXCL
qui lancera une OSError si le même nom de fichier existe déjà. Django détecte cette erreur puis appelleget_available_name
pour obtenir un nouveau nom.Je pense donc que la bonne façon est de remplacer
_save
et d'appeler os.open () sans indicateuros.O_EXCL
. La modification est assez simple mais la méthode est un peu longue donc je ne la colle pas ici. Dites-moi si vous avez besoin de plus d'aide :)la source
get_available_name
est que lorsque vous téléchargez un fichier avec le même nom, le serveur entrera dans une boucle sans fin. Puisque_save
vérifie le nom du fichier et décide d'en obtenir un nouveau, ilget_available_name
retourne toujours le double. Vous devez donc remplacer les deux.J'ai eu exactement le même problème! puis je me rends compte que mes modèles étaient à l'origine de cela. 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 ce problème 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 avoir réalisé que cela a plus de sens, car si je veux que le même fichier soit enregistré plus d'un dans ma base de données, je dois créer une autre table pour cela!
Je suppose que vous pouvez aussi résoudre votre problème comme ça, en espérant simplement que vous pourrez changer les modèles!
ÉDITER
Aussi je suppose que vous pouvez utiliser un stockage différent, comme celui-ci par exemple: SymlinkOrCopyStorage
http://code.welldev.org/django-storages/src/11bef0c2a410/storages/backends/symlinkorcopy.py
la source
Vous devez définir votre propre stockage, l'hériter de FileSystemStorage et remplacer l'
OS_OPEN_FLAGS
attribut de classe etget_available_name()
méthode de :Version Django: 3.1
Projet / core / files / storages / backends / local.py
import os from django.core.files.storage import FileSystemStorage class OverwriteStorage(FileSystemStorage): """ FileSystemStorage subclass that allows overwrite the already existing files. Be careful using this class, as user-uploaded files will overwrite already existing files. """ # The combination that don't makes os.open() raise OSError if the # file already exists before it's opened. OS_OPEN_FLAGS = os.O_WRONLY | os.O_TRUNC | os.O_CREAT | getattr(os, 'O_BINARY', 0) def get_available_name(self, name, max_length=None): """ This method will be called before starting the save process. """ return name
Dans votre modèle, utilisez votre OverwriteStorage personnalisé
myapp / models.py
from django.db import models from core.files.storages.backends.local import OverwriteStorage class MyModel(models.Model): my_file = models.FileField(storage=OverwriteStorage())
la source