У меня есть существующий файл на диске (например, /folder/file.txt) и поле модели FileField в Django.
Когда я делаю
instance.field = File(file('/folder/file.txt'))
instance.save()
он повторно сохраняет файл как file_1.txt
(в следующий раз и _2
т. д.).
Я понимаю, почему, но я не хочу такого поведения - я знаю, что файл, с которым я хочу связать поле, действительно ждет меня, и я просто хочу, чтобы Django указывал на него.
Как?
FileField
. Каждый раз, когдаFileField
сохраняется a, создается новая копия файла. Было бы довольно просто добавить опцию, чтобы этого избежать.Ответы:
Если вы хотите сделать это постоянно, вам необходимо создать свой собственный класс 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
Теперь в вашей модели вы используете модифицированный MyFileStorage
from mystuff.customs import MyFileStorage mfs = MyFileStorage() class SomeModel(model.Model): my_file = model.FileField(storage=mfs)
источник
FilePathField
либо в виде обычного текста.просто
instance.field.name
укажите путь к вашему файлунапример
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>
источник
MEDIA_ROOT
, то есть.doc.file = 'path/to/file'
попробуйте это ( док ):
источник
Правильно написать собственный класс хранилища. Однако
get_available_name
это неправильный метод переопределения.get_available_name
вызывается, когда Django видит файл с таким же именем и пытается получить новое доступное имя файла. Это не метод, который вызывает переименование. метод вызвал то есть_save
. Комментарии_save
довольно хороши, и вы можете легко найти, что он открывает файл для записи с флагом,os.O_EXCL
который выдает ошибку OSError, если такое имя файла уже существует. Django перехватывает эту ошибку, а затем вызываетget_available_name
для получения нового имени.Поэтому я думаю, что правильный способ - переопределить
_save
и вызвать os.open () без флагаos.O_EXCL
. Модификация довольно проста, однако метод немного длинный, поэтому я не вставляю его здесь. Скажите, если вам нужна дополнительная помощь :)источник
get_available_name
заключается в том, что когда вы загружаете файл с тем же именем, сервер попадет в бесконечный цикл. Поскольку_save
проверяет имя файла и решает получить новое, ноget_available_name
все равно возвращает дубликат. Так что вам нужно переопределить оба.У меня была точно такая же проблема! затем я понимаю, что причиной этого были мои Модели. Например, у меня были такие модели:
class Tile(models.Model): image = models.ImageField()
Затем я хотел иметь больше одной плитки, ссылающейся на один и тот же файл на диске! Я нашел способ решить эту проблему, изменив структуру моей модели на это:
class Tile(models.Model): image = models.ForeignKey(TileImage) class TileImage(models.Model): image = models.ImageField()
Что после того, как я понял, что это имеет больше смысла, потому что, если я хочу, чтобы один и тот же файл сохранялся более одного в моей БД, я должен создать для него другую таблицу!
Думаю, вы тоже можете решить свою проблему, просто надеясь, что вы сможете изменить модели!
РЕДАКТИРОВАТЬ
Также я думаю, вы можете использовать другое хранилище, например, это: SymlinkOrCopyStorage
http://code.welldev.org/django-storages/src/11bef0c2a410/storages/backends/symlinkorcopy.py
источник
Вы должны определить собственное хранилище, унаследовать его от FileSystemStorage и переопределить
OS_OPEN_FLAGS
атрибут иget_available_name()
метод класса :Версия Django: 3.1
Проект / ядро / файлы / хранилища / бэкэнды / 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
В вашей модели используйте свой собственный OverwriteStorage
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())
источник