我正在尝试在我的 Django 项目中实现多重上传。在执行与此问题的答案类似的操作后,我在提交时收到
No file was submitted. Check the encoding type on the form.
表单错误(self.errors == <ul class="errorlist"><li>image<ul class="errorlist"><li>No file was submitted. Check the encoding type on the form.</li></ul></li></ul>
)。可能是什么问题呢?你能帮我一下吗?
我的
models.py:
from PIL import Image as I
class Galery(models.Model):
user = models.ForeignKey(CustomUser, on_delete=models.CASCADE)
description = models.TextField(blank=True)
def __str__(self):
return self.user.userprofile.username + " - " + self.description
class Image(models.Model):
galery = models.ForeignKey(Galery, on_delete=models.CASCADE)
image = models.ImageField(upload_to='photos', blank=True, null=True)
def save(self, *args, **kwargs):
img = I.open(self.image.name)
img.resize(size=(300, 300))
img.save(self.image.name)
return super(Image, self).save(*args, **kwargs)
我的
forms.py:
class CustomFileInput(forms.ClearableFileInput):
allow_multiple_selected = True
class AddPhotoForm(forms.ModelForm):
description = forms.CharField(widget=forms.Textarea(), required=False)
class Meta:
model = Galery
fields = ['description']
def save(self, commit=True):
if commit:
post = Galery.objects.create(
user=self.instance,
description=self.cleaned_data['description']
)
return post
class AddImagesForm(AddPhotoForm):
image = forms.FileField(widget=CustomFileInput(attrs={'multiple': True}), required=True)
class Meta(AddPhotoForm.Meta):
fields = AddPhotoForm.Meta.fields + ['image']
我的
views.py:
class AddPhotoView(CreateView):
template_name = 'add-photo.html'
form_class = AddImagesForm
success_url = 'my-space'
def get(self, request, *args, **kwargs):
form = self.form_class()
return render(request, self.template_name, context={'form': form})
def post(self, request, *args, **kwargs):
form = self.form_class(request.POST,
request.FILES,
instance=request.user)
photos = request.FILES.getlist('image')
if photos:
if form.is_valid():
galery = form.save()
for photo in photos:
Image.objects.create(galery=galery, image=photo)
return redirect(self.success_url)
else:
messages.error(request, message='Upload at least one photo!')
return render(request, self.template_name, context={'form': form})
我的
add-photo.html
{% load widget_tweaks %}
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
<div class="d-flex justify-content-center">
{% render_field form.image name="image" %}
</div><br>
<div class="d-flex justify-content-center">
<ul class="list-group" id="list">
</ul>
</div><br>
<div class="d-flex justify-content-center">
<b>Add description: </b>
</div><br>
<div class="d-flex justify-content-center">
{% render_field form.description class="form-control" style="width: 300px;" placeholder="Write description here..." %}
</div><br>
<div class="d-flex justify-content-center">
<button style="width: 200px;" class="btn btn-primary" type="submit">Post</button>
</div>
</form>
我将非常感谢任何可以帮助我的人。谢谢!
用户逻辑的建模似乎有点奇怪。您似乎使用了
CustomUser
,我认为这是用户模型,但是如果您制作自定义用户模型,那么拥有单独的 UserProfile
模型没有多大意义:创建自定义用户模型通常已完成 完全以避免制作额外的模型。
但无论如何,我认为你正在实现方式太多的样板代码。因此,例如
AddPhotoForm
无法与 commit=False
一起使用,并且不能再用于 编辑 Galery
。
主要问题可能是 Django 的内置
FileField
无法处理多个文件,或者至少默认情况下不能。我们必须创建一个表单字段,以便在上传多个表单字段时对其进行验证,例如使用文档中指定的表单字段[Django-doc]:
class MultipleFileInput(forms.ClearableFileInput):
allow_multiple_selected = True
class MultipleFileField(forms.FileField):
def __init__(self, *args, **kwargs):
kwargs.setdefault("widget", MultipleFileInput())
super().__init__(*args, **kwargs)
def clean(self, data, initial=None):
single_file_clean = super().clean
if isinstance(data, (list, tuple)):
result = [single_file_clean(d, initial) for d in data]
else:
result = single_file_clean(data, initial)
return result
表单字段的新 clean
方法是必要的,因为我们将处理多个 项目。 现在我们可以制作一个
Galery
表格:
class AddPhotoForm(forms.ModelForm):
image = MultipleFileField()
class Meta:
model = Galery
fields = ['description']
def save(self, commit=True):
result = super().save(commit=commit)
if commit:
for image in self.cleaned_data['image']:
Image(galery=result, image=image).save()
return result
现在我们可以让 CreateView
完成它的工作:
from django.contrib.auth.mixins import LoginRequiredMixin
class AddPhotoView(LoginRequiredMixin, CreateView):
template_name = 'add-photo.html'
form_class = AddImagesForm
success_url = 'my-space'
def form_valid(self, form):
form.instance.user = self.request.user
return super().form_valid(form)
def form_invalid(self, form):
messages.error(self.request, message='Upload at least one photo!')
return super().form_invalid(form)