ディスクに既存のファイル(たとえば/folder/file.txt)とDjangoのFileFieldモデルフィールドがあります。
私がする時
instance.field = File(file('/folder/file.txt'))
instance.save()
ファイルをfile_1.txt
として保存し直します(次回は_2
など)。
理由はわかりますが、この動作は望ましくありません。フィールドに関連付けたいファイルが実際にそこにあることを知っており、Djangoがそれを指すようにするだけです。
どうやって?
これを永続的に行いたい場合は、独自の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)
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>
これを試してください( doc ):
instance.field.name = <PATH RELATIVE TO MEDIA_ROOT>
instance.save()
独自のストレージクラスを記述するのは正しいことです。ただし、get_available_name
はオーバーライドする正しい方法ではありません。
get_available_name
は、Djangoが同じ名前のファイルを検出し、使用可能な新しいファイル名を取得しようとしたときに呼び出されます。名前を変更するのはメソッドではありません。原因となったメソッドは_save
です。 _save
のコメントは非常に優れており、同じファイル名が既に存在する場合にOSErrorをスローするフラグos.O_EXCL
を使用して書き込み用にファイルを開くことが簡単にわかります。 Djangoはこのエラーをキャッチし、get_available_name
を呼び出して新しい名前を取得します。
正しい方法は、_save
をオーバーライドし、フラグos.O_EXCL
なしでos.open()を呼び出すことだと思います。変更は非常に簡単ですが、方法は少し長いので、ここに貼り付けません。さらにヘルプが必要な場合は教えてください:)
私はまったく同じ問題を抱えていました!私のモデルがそれを引き起こしていることに気付きます。例:私は次のようにモデルを作成しました:
class Tile(models.Model):
image = models.ImageField()
次に、ディスク内の同じファイルを参照する1つ以上のタイルが必要でした!それを解決するために私が見つけた方法は、私のモデル構造をこれに変更しました:
class Tile(models.Model):
image = models.ForeignKey(TileImage)
class TileImage(models.Model):
image = models.ImageField()
私がそれを理解した後、同じファイルをDBに保存したい場合は別のテーブルを作成する必要があるため、それはより理にかなっています!
モデルを変更できることを期待して、そのような問題も解決できると思います!
[〜#〜] edit [〜#〜]
また、たとえば次のような別のストレージを使用できると思います:SymlinkOrCopyStorage
http://code.welldev.org/Django-storages/src/11bef0c2a410/storages/backends/symlinkorcopy.py