[英]How to create multiple images upload in Django CreateView?
我有一个 Django 项目,我在这个项目中创建了一个帖子操作,因此用户将能够共享多个图片帖子。 但我有一个问题。 我不能写多张图片上传function。 我看了很多内容,但它不起作用。 它要么报告问题,要么没有将上下文发送到我想要的 HTML 页面。 请帮我。 我要的多图 function 应该在CreateView
下,应该和它放在同一个模板里。 此外,应该有 4 个图像上传按钮,最后一个应该分配多个功能(到 HTML 标签)。
模型.py:
class Photo(models.Model):
post= models.ForeignKey(Person, on_delete=models.CASCADE)
image = models.ImageField(upload_to=get_image_filename)
uploaded_at = models.DateTimeField(auto_now_add=True)
视图.py:
class PersonCreateView(CreateView):
model = Person
form_class = PersonForm
success_url = reverse_lazy('person_changelist')
forms.py:
class PhotoForm(forms.ModelForm):
image = forms.ImageField(label='Image')
class Meta:
model = Photo
fields = ('image', )
class PersonForm(forms.ModelForm):
title = forms.CharField(max_length=128)
body = forms.CharField(max_length=245, label="Item Description.")
file_field = forms.FileField(widget=forms.ClearableFileInput(attrs={'multiple': True}))
class Meta:
model = Person
widgets = {
'valyuta': forms.RadioSelect,
'barter': forms.CheckboxInput,
}
fields = ('country', 'city', 'ban', 'yurus', 'reng', 'qiymet', 'valyuta', 'yanacaqnovu', 'oturucu', 'squtu', 'buraxilisili', 'hecm', 'seher', 'barter', 'metin')
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['city'].queryset = City.objects.none()
if 'country' in self.data:
try:
country_id = int(self.data.get('country'))
self.fields['city'].queryset = City.objects.filter(country_id=country_id).order_by('name')
except (ValueError, TypeError):
pass # invalid input from the client; ignore and fallback to empty City queryset
elif self.instance.pk:
self.fields['city'].queryset = self.instance.country.city_set.order_by('name')
看看这是否有效。 创建一个简单的 HTML 表单而不是 Django 的模型表单
<form enctype="multipart/form-data" action="" method="post">
<input type="file" name="uploaded_images" accept="image/*" multiple>
<input type="submit" name="upload" value="Upload">
</form>
在您看来:
if request.method == 'POST':
for afile in request.FILES.getlist('uploaded_images'):
#Save images in respective models with the links to other models
return redirect('back/to/same/url')
这将使用户能够一次上传多个图像,您将能够轻松处理单个图像。
我在同样的问题上挣扎,但最终我成功了。 所以我想分享我的解决方案。 首先,我们需要创建 2 个模型,其中一个用于放置ImageField
并使用 ForeignKey 与第一个模型连接。
模型.py
class Item(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="items")
name = models.CharField(max_length=100)
class ItemImage(models.Model):
item = models.ForeignKey(Item, on_delete=models.CASCADE)
img = models.ImageField(default="store/default_noitem.jpg", upload_to=get_image_dir)
然后使用inlineformset_factory
创建表单。 它在通过外键处理相关对象的情况下尤其有用。
表格.py
from django import forms
from django.forms.models import inlineformset_factory
from .models import Item, ItemImage
class ItemImageForm(forms.ModelForm):
class Meta:
model = ItemImage
exclude = ()
class ItemForm(forms.ModelForm):
class Meta:
model = Item
fields = ["name",]
ItemImageFormSet = inlineformset_factory(
Item, ItemImage, form=ItemImageForm,
fields=['img'], extra=3, can_delete=True # <- place where you can enter the nr of img
)
最后
视图.py
class ItemCreateView(LoginRequiredMixin, SuccessMessageMixin, CreateView):
template_name = "items/add_item_form.html"
success_message = 'Item successfully added!'
form_class = ItemForm
def get_context_data(self, **kwargs):
data = super(ItemCreateView, self).get_context_data(**kwargs)
data['form_images'] = ItemImageFormSet()
if self.request.POST:
data['form_images'] = ItemImageFormSet(self.request.POST, self.request.FILES)
else:
data['form_images'] = ItemImageFormSet()
return data
def form_valid(self, form):
context = self.get_context_data()
form_img = context['form_images']
with transaction.atomic():
form.instance.user = self.request.user
self.object = form.save()
if form_img.is_valid():
form_img.instance = self.object
form_img.save()
return super(ItemCreateView, self).form_valid(form)
请记住在 formset 内添加(self.request.POST, self.request.FILES)
并在<form>
标签所在的 html 内添加enctype="multipart/form-data"
。
在没有PhotoForm
class 和inlineformset_factory
的情况下接近。
models.py
class Photo(models.Model):
post= models.ForeignKey(
Person, on_delete=models.CASCADE, related_name="person_images"
)
image = models.ImageField(upload_to=get_image_filename)
uploaded_at = models.DateTimeField(auto_now_add=True)
views.py
class PersonCreateView(LoginRequiredMixin, SuccessMessageMixin, CreateView):
form_class = PersonForm
template_name = "pages/add_person.html"
success_url = reverse_lazy("person_changelist")
success_message = _("Person created successfully!")
def form_valid(self, form):
form.instance.user = self.request.user
person_data = form.save()
# Save the images of person.
with transaction.atomic():
images = self.request.FILES.getlist("images")
for image in images:
form.instance.person_images.create(post=person_data, image=image)
return super().form_valid(form)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.