Saya memiliki berkas yang ada di disk (katakanlah /folder/file.txt) dan bidang model FileField di Django.
Ketika saya melakukannya
instance.field = File(file('/folder/file.txt'))
instance.save()
itu menyimpan ulang file sebagai file_1.txt
(saat berikutnya _2
, dll.).
Saya mengerti mengapa, tetapi saya tidak ingin perilaku ini - saya tahu berkas yang saya inginkan terkait dengan bidang tersebut benar-benar ada di sana menunggu saya, dan saya hanya ingin Django menunjukkannya.
Bagaimana?
FileField
. Setiap kali aFileField
disimpan, salinan baru dari file tersebut dibuat. Akan sangat mudah untuk menambahkan opsi untuk menghindari hal ini.Jawaban:
Jika Anda ingin melakukan ini secara permanen, Anda perlu membuat kelas FileStorage Anda sendiri
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
Sekarang dalam model Anda, Anda menggunakan MyFileStorage yang telah dimodifikasi
from mystuff.customs import MyFileStorage mfs = MyFileStorage() class SomeModel(model.Model): my_file = model.FileField(storage=mfs)
sumber
FilePathField
teks biasa atau teks biasa.cukup setel
instance.field.name
ke jalur file Andamisalnya
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>
sumber
MEDIA_ROOT
, yaitu.doc.file = 'path/to/file'
coba ini ( dok ):
sumber
Menulis kelas penyimpanan sendiri adalah hak. Namun
get_available_name
ini bukanlah metode yang tepat untuk diganti.get_available_name
dipanggil ketika Django melihat sebuah berkas dengan nama yang sama dan mencoba mendapatkan nama berkas baru yang tersedia. Bukan metode yang menyebabkan penggantian nama. metode yang menyebabkan itu_save
. Komentar di_save
cukup bagus dan Anda dapat dengan mudah menemukannya membuka file untuk menulis dengan flagos.O_EXCL
yang akan memunculkan OSError jika nama file yang sama sudah ada. Django menangkap Kesalahan ini kemudian memanggilget_available_name
untuk mendapatkan nama baru.Jadi menurut saya cara yang benar adalah menimpa
_save
dan memanggil os.open () tanpa flagos.O_EXCL
. Modifikasinya cukup sederhana namun metodenya agak lama jadi saya tidak paste disini. Beri tahu saya jika Anda membutuhkan bantuan lebih lanjut :)sumber
get_available_name
adalah ketika Anda mengunggah file dengan nama yang sama, server akan mengalami loop tanpa akhir. Sejak_save
memeriksa nama file dan memutuskan untuk mendapatkan yang baru namunget_available_name
tetap mengembalikan yang duplikat. Jadi, Anda perlu mengganti keduanya.Saya punya masalah yang persis sama! kemudian saya menyadari bahwa Model saya menyebabkan itu. contoh saya membuat model saya seperti ini:
class Tile(models.Model): image = models.ImageField()
Kemudian, saya ingin memiliki lebih dari satu ubin yang mereferensikan file yang sama di disk! Cara yang saya temukan untuk menyelesaikannya adalah dengan mengubah struktur Model saya menjadi ini:
class Tile(models.Model): image = models.ForeignKey(TileImage) class TileImage(models.Model): image = models.ImageField()
Yang setelah saya sadari itu lebih masuk akal, karena jika saya ingin file yang sama disimpan lebih dari satu di DB saya, saya harus membuat tabel lain untuk itu!
Saya rasa Anda juga bisa menyelesaikan masalah Anda seperti itu, hanya berharap Anda bisa mengubah modelnya!
EDIT
Saya rasa Anda juga dapat menggunakan penyimpanan yang berbeda, seperti ini misalnya: SymlinkOrCopyStorage
http://code.welldev.org/django-storages/src/11bef0c2a410/storages/backends/symlinkorcopy.py
sumber
Anda harus menentukan penyimpanan Anda sendiri, mewarisinya dari FileSystemStorage, dan mengganti
OS_OPEN_FLAGS
atribut danget_available_name()
metode kelas :Versi Django: 3.1.0
Proyek / 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
Di model Anda, gunakan OverwriteStorage kustom Anda
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())
sumber