"上传" Django中的磁盘文件

时间:2017-09-15 19:13:42

标签: python django file-upload django-models

我在python中生成一个文件,并希望"上传"该文件到django数据库。这样它就会自动放入媒体文件夹中,并与我的应用程序的所有其他文件整齐地组织在一起。

现在我在尝试这里:(使用类型提示,因为它的python 3.6)

# forms.py
class UploadForm(forms.ModelForm):
    class Meta:
        model = UploadedFile
        fields = ('document',)

# models.py
class UploadedFile(models.Model):
    document = models.FileField(upload_to=get_upload_path)

    # mimetype is generated by filename on save
    mimetype = models.CharField(max_length=255)

    # ... additional fields like temporary

def get_upload_path(instance: UploadedFile, filename):
    if instance.temporary:
        return "uploaded_files/temp/" + filename
    return "uploaded_files/" + filename

# views.py, file_out has been generated
with open(file_out, 'rb') as local_file:
    from django.core.files import File
    form = UploadForm(dict(), {'document': File(local_file)})
    print(form.errors)
    if form.is_valid():
        file = form.save(commit=False)
        # ... set additional fields
        file.save()
        form.save_m2m()
        return file

现在这不是我尝试过的唯一一件事。首先我直接设置了FileField,但导致save()失败,同时设置了mimetype字段。因为原始文件位于媒体文件夹之外,因此会触发可疑文件操作。

此外,该表单通过form.errors提供了有关"上传"的一些反馈。

根据我的方法,save()如上所述失败 - 意味着"上传"实际上并不复制媒体文件夹中的文件 - 或者表单返回没有文件传输的错误,并告诉检查表单协议。

现在我的理论是,我必须去初始化我自己的InMemoryUploadedFile实例,但我自己无法弄清楚如何做到这一点,并且互联网上没有可用的文档。

感觉我从一开始就采取了错误的方法。如何正确地做到这一点?

2 个答案:

答案 0 :(得分:1)

您是否定义了get_upload_path?如果没有,这可以解释你得到的错误。

从我所看到的你走在正确的轨道上。如果您不需要上传的动态路径,如果您只想在media/uploads中使用它们,则可以传递upload_to的字符串值(来自Django docs):

# file will be uploaded to MEDIA_ROOT/uploads
document = models.FileField(upload_to='uploads/')

答案 1 :(得分:0)

首先,感谢Franey指示我storage documentation引导我contentfile documentation

ContentFile实际上解决了这个问题,因为它基本上是我正在寻找的InMemoryUploadedFile的自我实例化版本。它是未存储在磁盘上的django File

以下是完整的解决方案:

# views.py, file_out has been generated
with open(file_out, 'rb') as local_file:
    from django.core.files.base import ContentFile

    # we need to provide a name. Otherwise the Storage.save
    # method reveives a None-parameter and breaks.
    form = UploadForm(dict(), {'document': ContentFile(local_file.read(), name=name)})
    if form.is_valid():
        file = form.save(commit=False)
        # ... set additional fields
        file.save()
        form.save_m2m()
        return file