如何以编程方式将本地文件上载为Django模型字段?

2024-10-02 02:28:55 发布

您现在位置:Python中文网/ 问答频道 /正文

尝试从本地路径将文件上载到FileField时遇到问题

我已在S3bucket中正确配置了CDN后端,并将其用作我的一个模型字段的PrivateMediaStorage

class MyModel(models.Model):
    some_file = models.FileField(storage=PrivateMediaStorage())
    ...

使用这个非常简单的配置,每当我通过django-admin创建/更新模型时,它都会被保存,并且作为some_file附加的文件会正确地上传到S3bucket

然而,如果我尝试以编程方式创建/更新模型实例,比如说通过自定义manage.py命令,则会创建模型实例本身,但不会将附件上载到CDN。下面是我用来上传文件的代码的简化版本:

class Command(BaseCommand):
    help = 'Creates dummy instance for quicker configuration'

    def handle(self, *args, **options):
        some_file = os.path.join(os.path.dirname(__file__), '../../../temporary/some_image.png')

        if not os.path.exists(some_file):
            raise CommandError(f'File {some_file} does not exist')
        else: 
            instance, created = MyModel.objects.get_or_create(defaults={'some_file': some_file}, ...)

我的实现中缺少了什么,需要调整什么以允许从本地存储上载文件


Tags: 文件path实例instance模型osmodelscdn
2条回答

您正在向some_file字段传递一个字符串(os.path.join()的结果),但需要向其传递一个实际的^{}对象

直接在模型上保存文件的最简单方法是使用^{}'s ^{}方法

作为上述案例的工作解决方案,创建记录的有效方法是:

instance = MyModel.objects.create(some_file=File(file=open(some_file, 'rb'), name='some_name.png'))

或者更好地使用pathlib动态获取名称:

from pathlib import Path

instance = MyModel.objects.create(some_file=File(file=open(some_file, 'rb'), name=Path(some_file).name))

请注意,基于文件获取行不太可能起作用,因为每次打开文件时,使用File实例作为参数执行get_or_create()可能每次都会创建一个新行。最好将文件字段放入defaults

instance, created = MyModel.objects.get_or_create(
    some_other_field=..., 
    defaults={'some_file': File(
        file=open(some_file, 'rb'), 
        name=pathlib.Path(some_file).name
        )}
)

您也可以这样做。

      some_file = os.path.join(os.path.dirname(__file__), '../../../temporary/some_image.png')
instance.some_file.name = some_file
instance.save()

相关问题 更多 >

    热门问题