Django updateview (cbv and fbv) to upload multiple files not working

I am trying to upload files (single and multiple) with an updateview (cbv and fbv) via an update template but I keep getting a 'This field is required' error when i submit and the files don't get uploaded of course. All required fields are filled with valid data types and the file upload fields are optional, so I don't understand where this error is coming from.

I strongly suspect there's an error in my view specifically in the 'if form.is_valid():' section. I tried using both fbv and cbv, still i get the same error. I have even created a seperate model for the multiple files upload field and a seperate form class that extends the updateform class, still i get the same error.

I am stumped. Please whatever help can be rendered will be highly appreciated.

Thanks.

this is the model for the multiple files upload field

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)

this is my 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

this is my 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)

this is my fbv

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))

this is the html code for the multiple files upload field

                        <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>

I was able to figure out the problem. It was the ID field in my models.py. It was set to models.IntegerField instead of models.AutoField or models.BigAutoField, so it was expecting an input from the user instead of django automatically filling and incrementing it

# what caused the error
id = models.IntegerField(primary_key=True)


# solution
id = models.BigAutoField(primary_key=True)
Back to Top