Tengo un archivo existente en el disco (digamos /folder/file.txt) y un campo de modelo FileField en Django.
Cuando lo hago
instance.field = File(file('/folder/file.txt'))
instance.save()
vuelve a guardar el archivo como file_1.txt
(la próxima vez _2
, etc.).
Entiendo por qué, pero no quiero este comportamiento: sé que el archivo con el que quiero que se asocie el campo está realmente allí esperándome, y solo quiero que Django lo señale.
¿Cómo?
FileField
. Siempre queFileField
se guarda un, se crea una nueva copia del archivo. Sería bastante sencillo agregar una opción para evitar esto.Respuestas:
Si desea hacer esto de forma permanente, debe crear su propia clase 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
Ahora en su modelo, usa su MyFileStorage modificado
from mystuff.customs import MyFileStorage mfs = MyFileStorage() class SomeModel(model.Model): my_file = model.FileField(storage=mfs)
fuente
FilePathField
o simplemente como texto sin formato.solo establezca
instance.field.name
la ruta de su archivop.ej
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>
fuente
MEDIA_ROOT
, eso es.doc.file = 'path/to/file'
prueba esto ( doc ):
fuente
Es correcto escribir su propia clase de almacenamiento. Sin embargo,
get_available_name
no es el método correcto para anular.get_available_name
se llama cuando Django ve un archivo con el mismo nombre e intenta obtener un nuevo nombre de archivo disponible. No es el método el que provoca el cambio de nombre. el método provocó eso_save
. Los comentarios_save
son bastante buenos y puede encontrar fácilmente que abre un archivo para escribir con una banderaos.O_EXCL
que arrojará un error de OS si ya existe el mismo nombre de archivo. Django detecta este error y luego llamaget_available_name
para obtener un nuevo nombre.Entonces creo que la forma correcta es anular
_save
y llamar a os.open () sin banderaos.O_EXCL
. La modificación es bastante simple, sin embargo, el método es un poco largo, así que no lo pego aquí. Dime si necesitas más ayuda :)fuente
get_available_name
es cuando carga un archivo con el mismo nombre, el servidor entrará en un bucle sin fin. Dado que_save
verifica el nombre del archivo y decide obtener uno nuevo, sin embargo,get_available_name
aún devuelve el duplicado. Entonces necesitas anular ambos.¡Tuve exactamente el mismo problema! luego me doy cuenta de que mis modelos estaban causando eso. ejemplo, tengo mis modelos así:
class Tile(models.Model): image = models.ImageField()
¡Entonces, quería tener más de un mosaico que hiciera referencia al mismo archivo en el disco! La forma en que encontré para resolver eso fue cambiar la estructura de mi modelo a esto:
class Tile(models.Model): image = models.ForeignKey(TileImage) class TileImage(models.Model): image = models.ImageField()
Lo cual después me doy cuenta de que tiene más sentido, porque si quiero que el mismo archivo se guarde más de uno en mi base de datos, ¡tengo que crear otra tabla para él!
Supongo que también puedes resolver tu problema así, ¡solo esperando que puedas cambiar los modelos!
EDITAR
También supongo que puede usar un almacenamiento diferente, como este, por ejemplo: SymlinkOrCopyStorage
http://code.welldev.org/django-storages/src/11bef0c2a410/storages/backends/symlinkorcopy.py
fuente
Debe definir su propio almacenamiento, heredarlo de FileSystemStorage y anular el método
OS_OPEN_FLAGS
y el atributo de claseget_available_name()
:Versión de Django: 3.1
Proyecto / 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
En su modelo, use su 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())
fuente