Django updateview (cbv и fbv) для загрузки нескольких файлов не работает
Я пытаюсь загрузить файлы (один и несколько) с помощью обновления (cbv и fbv) через шаблон обновления, но я продолжаю получать ошибку 'This field is required' при отправке, и файлы, конечно, не загружаются. Все обязательные поля заполнены допустимыми типами данных, а поля загрузки файлов являются необязательными, поэтому я не понимаю, откуда берется эта ошибка.
Я сильно подозреваю, что в моем представлении есть ошибка, в частности в разделе 'if form.is_valid():'. Я пробовал использовать и fbv, и cbv, но все равно получаю ту же ошибку. Я даже создал отдельную модель для поля загрузки нескольких файлов и отдельный класс формы, который расширяет класс updateform, но все равно получаю ту же ошибку.
Я в тупике. Пожалуйста, любая помощь будет высоко оценена.
Спасибо.
это модель для поля загрузки нескольких файлов
class shareCapitalFiles(models.Model):
# Foreign key
coopform = models.ForeignKey(CoopForm, on_delete=models.CASCADE)
# Attach evidence of share capital
attach_share_capital = models.FileField('Attach Share Capital', upload_to="documents", blank=True)
вот мой forms.py
# Update Form
class updateCoopForm(forms.ModelForm):
nature_registration = forms.ChoiceField(widget=forms.RadioSelect(attrs={'class': 'flex inline-flex', 'cursor': 'pointer'}), choices=CoopForm.REGISTRATION_TYPE)
have_bye_laws = forms.ChoiceField(widget=forms.RadioSelect(attrs={'class': 'flex inline-flex', 'cursor': 'pointer'}), choices=CoopForm.BYE_LAWS_CHOICES)
attach_bye_laws = forms.FileField(required=False)
class Meta:
model = CoopForm
fields = '__all__'
widgets = {
'first_purpose': forms.Textarea(attrs={'rows':2}),
'second_purpose': forms.Textarea(attrs={'rows':2}),
'third_purpose': forms.Textarea(attrs={'rows':2}),
'first_origin_meeting_date': forms.DateInput(attrs={'type': 'date'}),
'second_origin_meeting_date': forms.DateInput(attrs={'type': 'date'})
}
class shareCapitalForm(updateCoopForm):
attach_share_capital = forms.FileField(label='Attach Share Capital',widget=forms.ClearableFileInput(attrs={'multiple': True}), required=False)
class Meta(updateCoopForm.Meta):
fields = updateCoopForm.Meta.fields
это мой cbv
class updateFormView(UpdateView):
model = CoopForm
form_class = shareCapitalForm
context_object_name = 'obj'
template_name = 'updateform.html'
def get_queryset(self):
return CoopForm.objects.all()
def get_success_url(self):
return reverse('formdetails', kwargs={'pk': self.object.id})
def get_context_data(self, **kwargs):
context = super(updateFormView, self).get_context_data(**kwargs)
if self.request.POST:
context['form'] = shareCapitalForm(self.request.POST, self.request.FILES, nstance=self.object)
else:
context['form'] = shareCapitalForm(instance=self.object)
return context
def post(self, request, *args, **kwargs):
self.object = self.get_object()
form_class = self.get_form_class()
form = self.get_form(form_class)
files = self.request.FILES.getlist('attach_share_capital')
if form.is_valid():
update = form.save(commit=False)
if files:
for f in files:
instance = shareCapitalFiles.objects.create(coopform=update, attach_share_capital=f)
instance.save()
messages.success(request, 'Files uploaded successfully')
#update.author = self.request.user
update.save()
return self.form_valid(form)
else:
return self.form_invalid(form)
это мой фбв
def updateformview(request, pk, *args, **kwargs):
# fetch the object related to passed id
obj = get_object_or_404(CoopForm, id=pk)
# pass the object as instance in form
form = shareCapitalForm(request.POST or None, request.FILES or None, instance=obj)
# get the template
template = loader.get_template('updateform.html')
# if the form is being updated
if request.method == 'POST':
# retrieve multiples files from model field
files = request.FILES.getlist('attach_share_capital')
# save the data from the form and
# redirect to detail_view
if form.is_valid():
update = form.save(commit=False)
update.save()
if files:
for f in files:
instance = shareCapitalFiles.objects.create(coopform=update, attach_share_capital=f)
instance.save()
return HttpResponseRedirect(reverse('formdetails', kwargs={'pk': id}))
context = {
'form': form,
'obj': obj
}
return HttpResponse(template.render(context, request))
вот html код для поля загрузки нескольких файлов
<div class="grid gap-6 mt-1 mx-auto md:grid-cols-2 lg:grid-cols-2 px-6 pt-4 pb-8 bg-stone-50 border border-1 border-gray-300 shadow-md">
<!-- Attach Share Capital -->
<div>
<label for="attach_share_capital" class="block mb-2 text-md font-bold text-gray-500">
{{ form.attach_share_capital.label }}
</label>
{% render_field form.attach_share_capital class+="cursor-pointer text-md md:text-md font-medium block rounded-sm w-full p-2 border border-2 border-gray-300 placeholder-gray-500 text-gray-600 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500" %}
<p class="mt-1 text-sm text-gray-500">PDF, DOC (WORD), PNG OR JPG formats only. You can attach multiple files</p>
</div>
{% if form.errors.attach_share_capital %}
<span class="text-red-600 font-medium">{{ form.errors.attach_share_capital }}</span>
{% endif %}
</div>
Мне удалось выяснить проблему. Это было поле ID в моем models.py. Оно было установлено в models.IntegerField вместо models.AutoField или models.BigAutoField, поэтому оно ожидало ввода от пользователя вместо того, чтобы django автоматически заполнял и увеличивал его
# what caused the error
id = models.IntegerField(primary_key=True)
# solution
id = models.BigAutoField(primary_key=True)