是的,有一个方便的方法。
首先声明一个图像类,类似于:
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 插件上传多个带有进度条的图像。