如何从 django admin 中的单个“选择文件”选择器上传多个图像

Kus*_*mal 8 python django django-2.0

我正在做这个模拟服装订购系统的小项目来提高我的 Django 技能。

我必须添加某个项目的几张图片(不是固定数字)。因此,在 Item 模型中使用固定数量的图像字段并不理想。所以,我想到了另一个模型,它只包含通过一个键连接到模型“项目”的图像。

现在我知道 django 具有内联选项,可以根据需要一一添加模型对象。但这似乎有点傻,因为您必须打开该对话框并一张一张地选择图像。

是否有可能有一个选择器,我们可以通过它一次选择多个文件并将它们添加到模型中?

Don*_*ald 11

是的,有一个方便的方法。首先声明一个图像类,例如:

class Image(models.Model):
    condo = models.ForeignKey(Condo, on_delete=models.CASCADE, related_name='images')
    image = models.FileField(upload_to="images/")
    uploaded_at = models.DateTimeField(auto_now_add=True)
Run Code Online (Sandbox Code Playgroud)

在表单创建中不要添加一行来呈现FileField

class ListingForm(forms.ModelForm):
    ...
    ...
    #photos = forms.FileField(required=False) #Don't do it.
Run Code Online (Sandbox Code Playgroud)

而是在模板中,在其他行中,也添加以下内容:

<form action="" method="post" autocomplete="off" enctype="multipart/form-data">
    {% csrf_token %}
    {{ your_form|crispy }} <br/>
    <input type="file" name="images" multiple>
    <input type="submit" value="Submit">
</form>
Run Code Online (Sandbox Code Playgroud)

在处理您的POST请求的视图中,您可以使用以下方式处理上传的图像:

from app.forms import Image


if request.method == 'POST':
...
...
    for file in request.FILES.getlist('images'):
        instance = Image(
            condo=Condo.objects.get(your_parent_objects_id),
            image=file
        )
        instance.save()
Run Code Online (Sandbox Code Playgroud)

这会为每个图像创建新的 Image 对象并将实际文件保存到您的媒体文件夹。

此外,由于可能存在恶意行为,我建议您重命名用户上传的文件。

我已经通过创建一个小函数并使用它而不是它的"images/"一部分来做到这一点。

import uuid
def images_directory_path(instance, filename):
    return '/'.join(['images', str(instance.condo_id.id), str(uuid.uuid4().hex + ".png")])

# in Image class (models.py)
image = models.FileField(upload_to=images_directory_path)
Run Code Online (Sandbox Code Playgroud)

最后一次修改为图像生成新名称 as uuid4,向它们添加 .png 扩展名并创建到media/文件夹的完整链接。

在此处输入图片说明

当然,没有验证上传文件的格式或大小是否有效,但这是另一个问题的主题。

您可以使用变量访问图像,images因为它是related_name所有连接到给定对象(在本例中为 Condo)的图像的变量。

最后,这是Vitor Freitas 的一篇关于使用 Javascript 插件上传带进度条的多张图片的精彩文章