我正在做这个模拟服装订购系统的小项目来提升我的django技能。
我必须添加某个项目的几张图片(不是固定的数字)。因此,在Item模型中使用固定数量的图像字段并不理想。所以,我想到了另一个模型,它只包含一个通过键连接到模型“项目”的图像。
现在我知道django有内联选项,可以根据需要逐个添加模型对象。但这似乎有点像吸盘,因为你必须打开那个对话框并逐个选择图像。
是否有可能有一个选择器,我们可以一次选择多个文件并将它们添加到模型中?
答案 0 :(得分:2)
是的,有一种方便的方法。 首先声明一个图像类,如:
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
访问图像,因为对于给定对象(在本例中为公寓),所有连接图像都是related_name
。
最后,这是关于使用Javascript插件上传带有进度条的多个图片的great article by Vitor Freitas。
答案 1 :(得分:0)
来自文档(https://docs.djangoproject.com/en/2.2/topics/http/file-uploads/):
上传多个文件 如果您要使用一个表单字段上传多个文件,请设置该字段的小部件的多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’),