Hey,
I have this form which includes document uploads. I used to just manage it via the default submit form from the browser, and the pass the files uploaded with request.FILES passed to the formset in the view, like so:
if self.request.POST:
form = self.get_form() # manages POST, instance internally from self
formset_document = DocumentFormSet(self.request.POST, self.request.FILES, instance=self.object)
And then the documents would get saved according this form/formest/model:
DocumentFormSet = inlineformset_factory(Produit, DocumentProduit,
form=DocumentsProduitForm,
extra=0,
can_delete=True)
class DocumentProduit(models.Model):
fk_produit = models.ForeignKey(Produit, on_delete=models.SET_DEFAULT,related_name="documents", null=False, blank=False, default=0)
document = models.FileField(upload_to=docprod_uploadto, verbose_name="Document Produit", blank=True, null=True)
filename = models.CharField(max_length=50, verbose_name="Nom du document", null=True, blank=True)
notes = models.TextField(verbose_name="Notes", blank=True, null=True)
class DocumentsProduitForm(ModelForm):
class Meta:
model = DocumentProduit
fields = ["document", "notes"]
widgets = {"document":FileInput(attrs={"class":"fileUploader"})}
Then I had to switch to making those request AJAX calls on the client side, using jquery, like so:
let csrftoken = $('input[name="csrfmiddlewaretoken"]').val();
$('form#mainform').append($input)
let data = $('form#mainform').serialize();
$.ajax({
url: url,
type: "POST",
data: data,
headers: {'X-CSRFToken':csrftoken},
success: ....,
error: .... })
And the form:
<form id="mainform" action="" method="post" enctype='multipart/form-data'>
{%csrf_token%}
....
<tbody id="documents_body">
{{ formset_document.management_form }}
{{ formset_document.non_form_errors }}
{% for form in formset_document %}
<tr>
{% if form.document.value %}
<td><a href="{{ form.document.value.url }}" class="download-on-click">{{ form.document.value.name}}</a> </td>
{% else %}
<td>{% field_error form.document.errors %}{{ form.document }}</td>
{% endif %}
{# <td>{% field_error form.filename.errors %}{{ form.filename }}</td>#}
<td>{% field_error form.notes.errors %}{{ form.notes }}</td>
<td>{{ form.DELETE }}</td>
<td style="display: none">{{ form.fk_produit }}</td>
<td style="display: none">{{ form.id }}</td>
</tr>
{% endfor %}
</tbody>
....
However in this case, request.FILES is empty on the server-side. Apparently with that switch I have lost part of the handling of those files that django provides (or perhaps ajax.post() doesn’t handle files in a form the same way that a regular submit does)?).
Any convenient way to “re-add” my files to request.FILES for the server-side? I’ve been able to “find” them with jquery selectors, like so:
$(".fileUploader").each(function(){
console.log(this.files[0])
})
But there has to be a more standard way to do this than messing around with jquery selectors?