Django 多文件字段

Posted

技术标签:

【中文标题】Django 多文件字段【英文标题】:Django Multiple File Field 【发布时间】:2012-07-16 18:30:09 【问题描述】:

是否有可以为 django 处理多个文件或多个图像的模型字段?还是将 ManyToManyField 设置为包含图像或文件的单独模型更好?

我需要一个在 django-admin 中带有上传界面的解决方案。

【问题讨论】:

模型字段不用于上传。您是希望将这些文件/图像存储在数据库中还是通过浏览器上传? 将它们存储在数据库中,与单个文件字段基本相同但可以对其进行迭代 【参考方案1】:

对于 2017 年及以后的人,有一个 special section in Django docs。我的个人解决方案是这样的(在管理员中成功运行):

class ProductImageForm(forms.ModelForm):
    # this will return only first saved image on save()
    image = forms.ImageField(widget=forms.FileInput(attrs='multiple': True), required=True)

    class Meta:
        model = ProductImage
        fields = ['image', 'position']

    def save(self, *args, **kwargs):
        # multiple file upload
        # NB: does not respect 'commit' kwarg
        file_list = natsorted(self.files.getlist('-image'.format(self.prefix)), key=lambda file: file.name)

        self.instance.image = file_list[0]
        for file in file_list[1:]:
            ProductImage.objects.create(
                product=self.cleaned_data['product'],
                image=file,
                position=self.cleaned_data['position'],
            )

        return super().save(*args, **kwargs)

【讨论】:

这个 natsorted 是从哪里来的? 找到了,我正在使用你的解决方案,但我在 file_list 上得到了空列表,你覆盖了你的 html 还是什么? 请在该行设置断点并检查self.files 中的内容。事情发生了变化,我只给出了一个想法,您必须测试并了解发生了什么。 self.files 已更改...我检查以获取 getlist('images') 您需要使用与模型中的字段相同的表单字段名称,因此如果您的模型有一个名为file 的字段,请不要将表单字段称为files-image 中的后缀也需要与您的字段名称匹配。您可能想要使用 ClearableFileInput 小部件,或者,如果在管理员中,请使用 admin.widgets.AdminFileWidget【参考方案2】:

不,没有一个字段知道如何存储 Django 附带的多个图像。上传的文件在模型中存储为文件路径字符串,所以本质上是一个CharField,知道如何转换成python。

典型的多图像关系构建为一个单独的图像模型,其中一个 FK 指向其相关模型,例如ProductImage -> Product

这种设置可以很容易地以Inline 的形式添加到 django 管理员中。

如果您确实是多对多关系,即从 1 个或多个 Gallery 对象引用 GalleryImages,则 M2M 字段将是有意义的。

【讨论】:

【参考方案3】:

我不得不将现有系统中的单个文件更改为多个文件,经过一番研究后最终使用了这个:https://github.com/bartTC/django-attachments

如果您想要自定义方法,应该很容易对模型进行子类化。

【讨论】:

【参考方案4】:

FilerFileField 和 FilerImageField 在一个模型中:

它们是 django.db.models.ForeignKey 的子类,因此适用相同的规则。唯一的区别是,不需要声明我们引用的模型(对于 FilerFileField 始终是 filer.models.File,对于 FilerImageField 始终是 filer.models.Image)。

简单示例models.py:

from django.db import models
from filer.fields.image import FilerImageField
from filer.fields.file import FilerFileField

class Company(models.Model):
    name = models.CharField(max_length=255)
    logo = FilerImageField(null=True, blank=True)
    disclaimer = FilerFileField(null=True, blank=True)

models.py中同一模型上的多个图像文件字段:

注意:related_name 属性是必需的,就像定义外键关系一样。

from django.db import models
from filer.fields.image import FilerImageField

class Book(models.Model):
    title = models.CharField(max_length=255)
    cover = FilerImageField(related_name="book_covers")
    back = FilerImageField(related_name="book_backs")

此答案代码取自django-filer document

【讨论】:

恐怕您回答的问题与所问的问题相反。 “单个字段但能够遍历它们”,一对多的关系。您提到的是多对一的解决方案。 这绝对不是 Dave 所要求的!他询问了在 django admin 中一次性上传多个文件(例如,当您想将 100 张图片上传到相册时)

以上是关于Django 多文件字段的主要内容,如果未能解决你的问题,请参考以下文章

django 多线程 + uWSGI 多线程 遇到的坑

Django的认证系统

我们如何在 django 管理搜索字段中搜索多对多字段

完全加入多对多字段 Django

Django:Syncdb 错误地警告多对多字段已过时

Django:在创建对象时搜索多对多字段