Eu tenho um arquivo existente no disco (digamos / pasta / arquivo.txt) e um campo de modelo FileField no Django.
Quando eu faço
instance.field = File(file('/folder/file.txt'))
instance.save()
ele salva o arquivo novamente como file_1.txt
(na próxima vez _2
, etc.).
Eu entendo o porquê, mas não quero esse comportamento - eu sei que o arquivo ao qual quero que o campo seja associado está realmente lá, esperando por mim, e só quero que o Django aponte para ele.
Quão?
FileField
. Sempre que umFileField
é salvo, uma nova cópia do arquivo é criada. Seria bastante simples adicionar uma opção para evitar isso.Respostas:
Se você quiser fazer isso permanentemente, você precisa criar sua própria 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
Agora em seu modelo, você usa seu MyFileStorage modificado
from mystuff.customs import MyFileStorage mfs = MyFileStorage() class SomeModel(model.Model): my_file = model.FileField(storage=mfs)
fonte
FilePathField
ou simplesmente como texto simples.apenas defina
instance.field.name
o caminho do seu arquivopor exemplo
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>
fonte
MEDIA_ROOT
, isto é.doc.file = 'path/to/file'
tente isto ( doc ):
fonte
É certo escrever sua própria classe de armazenamento. No entanto,
get_available_name
não é o método certo para substituir.get_available_name
é chamado quando o Django vê um arquivo com o mesmo nome e tenta obter um novo nome de arquivo disponível. Não é o método que causa a renomeação. o método causou isso_save
. Os comentários_save
são muito bons e você pode facilmente descobrir que ele abre um arquivo para escrever com o sinalizadoros.O_EXCL
que lançará um OSError se o mesmo nome de arquivo já existir. O Django detecta esse erro e então chamaget_available_name
para obter um novo nome.Portanto, acho que a maneira correta é substituir
_save
e chamar os.open () sem sinalizaros.O_EXCL
. A modificação é bastante simples, porém o método é um pouco demorado, então não colo aqui. Diga-me se precisar de mais ajuda :)fonte
get_available_name
é quando você carrega um arquivo com o mesmo nome, o servidor entrará em um loop infinito. Desde_save
verifica o nome do arquivo e decide obter um novo, porémget_available_name
ainda retorna o duplicado. Portanto, você precisa substituir ambos.Eu tive exatamente o mesmo problema! então eu percebo que meus modelos estavam causando isso. exemplo, eu tenho meus modelos assim:
class Tile(models.Model): image = models.ImageField()
Então, eu queria ter mais um bloco referenciando o mesmo arquivo no disco! A maneira que encontrei de resolver isso foi mudar minha estrutura de modelo para esta:
class Tile(models.Model): image = models.ForeignKey(TileImage) class TileImage(models.Model): image = models.ImageField()
Que depois de perceber que faz mais sentido, pois se eu quiser que o mesmo arquivo seja salvo mais de um no meu BD tenho que criar outra tabela para ele!
Eu acho que você pode resolver seu problema assim também, apenas esperando que você possa mudar os modelos!
EDITAR
Além disso, acho que você pode usar um armazenamento diferente, como este, por exemplo: SymlinkOrCopyStorage
http://code.welldev.org/django-storages/src/11bef0c2a410/storages/backends/symlinkorcopy.py
fonte
Você deve definir seu próprio armazenamento, herdá-lo de FileSystemStorage e substituir o
OS_OPEN_FLAGS
atributo e oget_available_name()
método de classe :Versão Django: 3.1
Projeto / 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
Em seu modelo, use seu OverwriteStorage personalizado
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())
fonte