【问题标题】:How to upload multiple images from a single "Choose Files" selector in django admin如何从 django admin 中的单个“选择文件”选择器上传多个图像
【发布时间】:2018-09-24 09:51:19
【问题描述】:

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

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

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

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

【问题讨论】:

标签: python django django-2.0


【解决方案1】:

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

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)

在表单创建中不要添加一行来显示FileField

class ListingForm(forms.ModelForm):
    ...
    ...
    #photos = forms.FileField(required=False) #Don't do it.

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

<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>

在处理您的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()

这将为每个图像创建新的 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)

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

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

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

最后,这是一个great article by Vitor Freitas,关于使用 Javascript 插件上传多个带有进度条的图像。

【讨论】:

    【解决方案2】:

    来自文档 (https://docs.djangoproject.com/en/2.2/topics/http/file-uploads/):

    上传多个文件 如果要使用一个表单字段上传多个文件,请设置字段小部件的 multiple HTML 属性:

    forms.py

    from django import forms
    
    class FileFieldForm(forms.Form):
        file_field = forms.FileField(widget=forms.ClearableFileInput(attrs={'multiple': 
    True}))
    

    然后重写你的 FormView 子类的 post 方法来处理多个文件上传:

    views.py

    from django.views.generic.edit import FormView
    from .forms import FileFieldForm
    
    class FileFieldView(FormView):
        form_class = FileFieldForm
        template_name = 'upload.html'  # Replace with your template.
        success_url = '...'  # Replace with your URL or reverse().
    
        def post(self, request, *args, **kwargs):
            form_class = self.get_form_class()
            form = self.get_form(form_class)
            files = request.FILES.getlist('file_field')
            if form.is_valid():
                for f in files:
                    instance = Image(image=file)  # match the model.
                    instance.save()
                return self.form_valid(form)
            else:
                return self.form_invalid(form)
    

    并添加一个模型:

    from django.db import models
    
    class Image(models.Model):
        image = models.FileField(upload_to='images/%Y/%m/%d')
        uploaded_at = models.DateTimeField(auto_now_add=True)
    

    并添加到 urls.py urlpatterns:

    path(‘upload/’,views.FileFieldView.as_view(),name=‘FileFieldView’),
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-08-24
      • 2020-05-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-26
      相关资源
      最近更新 更多