将Django的FileField设置为现有文件

Gua*_*ard 82 python django file

我在磁盘上有一个现有文件(例如/folder/file.txt)和Django中的FileField模型字段.

当我做

instance.field = File(file('/folder/file.txt'))
instance.save()
Run Code Online (Sandbox Code Playgroud)

它将文件重新保存为file_1.txt(下一次_2,等等).

我理解为什么,但我不想要这种行为 - 我知道我希望该字段与之关联的文件真的在那里等着我,我只想让Django指向它.

怎么样?

bar*_*ara 104

只需设置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>
Run Code Online (Sandbox Code Playgroud)

  • 你的`MEDIA_ROOT`的相对路径,即. (13认同)
  • 在这个例子中,我认为你也可以只做`doc.file ='path/to/file'` (7认同)

Bur*_*lid 20

如果要永久执行此操作,则需要创建自己的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
Run Code Online (Sandbox Code Playgroud)

现在在您的模型中,您使用修改后的MyFileStorage

from mystuff.customs import MyFileStorage

mfs = MyFileStorage()

class SomeModel(model.Model):
   my_file = model.FileField(storage=mfs)
Run Code Online (Sandbox Code Playgroud)

  • 不,因为存储引擎与模型相关联.您可以通过简单地将文件路径存储在`FilePathField`中或简单地作为纯文本来避免这一切. (2认同)
  • 该解决方案只是看似正确,因为该解决方案实际上删除了已存在的文件并创建一个具有相同名称的新文件。最后,它并没有像作者所写的那样“指向它”。想象一下这样的情况:用户想要指向一个大文件,但实际上最终删除了它并从头开始上传。 (2认同)

小智 12

试试这个(doc):

instance.field.name = <PATH RELATIVE TO MEDIA_ROOT> 
instance.save()
Run Code Online (Sandbox Code Playgroud)


x1a*_*1a0 5

编写自己的存储类是正确的。但是,get_available_name这不是重写的正确方法。

get_available_name当Django看到具有相同名称的文件并尝试获取新的可用文件名时,将调用。不是导致重命名的方法。造成的方法是_save。中的注释_save非常好,您可以轻松找到带有标志的打开待写入文件,os.O_EXCL如果已经存在相同的文件名,则会引发OSError。Django捕获此错误,然后调用get_available_name以获取新名称。

所以我认为正确的方法是_save不带flag 覆盖并调用os.open()os.O_EXCL。修改很简单,但是方法有点长,所以我不在这里粘贴。告诉我您是否需要更多帮助:)

  • “仅”覆盖“ get_available_name”的问题是当您上传具有相同名称的文件时,服务器将陷入无休止的循环。由于_save检查文件名并决定获取一个新文件,但是get_available_name仍然返回重复的文件名。因此,您需要同时覆盖两者。 (2认同)