Как использовать прозрачный флажок для ajax загрузки файлов с помощью modelform django

Я совсем новичок в django и ajax, поэтому прошу простить меня, если в моей работе есть какая-то большая ошибка или некрасивый код. Итак, я работаю над приложением, где пользователь должен загружать различные документы в modelForm (связанную с другой моделью 1:1). Пользователь, вероятно, не будет загружать все документы сразу. Я использую ajax, чтобы иметь индикатор выполнения для пользователя. Пока что загрузка работает нормально, замена документа на другой тоже работает, но у меня возникла проблема, когда дело доходит до использования прозрачного флажка, который django предоставляет, когда документ уже загружен. Используя submit и стандартный Post, флажок работает нормально. При использовании ajax он не работает.

models.py (не буду выкладывать все, так как там более 25 FileFields)

    class MandatVenteUpload(models.Model):
    mandat= models.OneToOneField('mandat_vente.MandatVente',  on_delete=models.CASCADE, primary_key=True)
    acte_propriete = models.FileField(upload_to=content_file_name, max_length=60 ,null=True, blank=True)
    carte_identite= models.FileField(upload_to=content_file_name, max_length=60 ,null=True, blank=True)
    diagnostic_amiante= models.FileField(upload_to=content_file_name, max_length=60 ,null=True, blank=True)
    diagnostic_assainissement= models.FileField(upload_to=content_file_name, max_length=60 ,null=True, blank=True) 
    diagnostic_electricite= models.FileField(upload_to=content_file_name, max_length=60 ,null=True, blank=True)
    [...]

views.py (использование исключения, так как если документ еще не загружен, то модель не существует)

@login_required
def mandat_vente_upload_view(request, num_mandat_upload):
    mandat_upload=get_object_or_404(MandatVente, id = num_mandat_upload)
    if mandat_upload.createur == request.user or request.user.is_staff:
        try:
            form_upload = MandatVenteUpload.objects.get(mandat=mandat_upload.id)
            form=MandatVenteUploadForm(mandat_upload, request.POST or None, request.FILES or None, instance=form_upload)
            if request.is_ajax() or request.method == 'POST':
                if form.is_valid():
                    print(request.POST)
                    print(request.FILES)
                    form.save()
                    return JsonResponse({'message': 'hell yeah'})
            return render(request, 'mandat_vente/upload_mandat.html', context={'form' : form})
        except MandatVenteUpload.DoesNotExist:
            print("ici")
            form = MandatVenteUploadForm(mandat_upload)
            if request.is_ajax() or request.method == 'POST':
                form=MandatVenteUploadForm(mandat_upload, request.POST or None, request.FILES or None)
                if form.is_valid():
                    print("exception")
                    form.save()
                    return JsonResponse({'message': 'hell yeah'})
            return render(request, 'mandat_vente/upload_mandat.html', context={'form' : form})
    else:
        return HttpResponse('Vous ne pouvez pas charger de documents pour ce mandat.')

upload_mandat.html

{% extends 'template_base.html' %}
{% block titre %} <title>Upload documents</title>
<script src="/static/main.js" defer></script>
{% endblock %} 
{% block contenu %}

    <div class="container">
        <div class="row justify-content-center">
            <div class="col-6 mt-4">
                <h1>Upload documents liés au mandat</h1>
                <hr class="my-4">
                <form id="upload-form" action="" method="POST" enctype="multipart/form-data" class="upload-docs-div">
                    {% csrf_token %}
                    {{form.as_p}}
                    <button type="submit" class="btn btn-primary">Envoyer</button>
                </form>
            </div>
        </div>
    </div>
    <div id="progress-box" class="not-visible">progress</div>
    <div id="cancel-box" class="not-visible">
        <button id="cancel-btn" class="btn btn-danger">Annuler</button>
    </div>

{% endblock %}

main.js (вырезание списка fd.append с другими документами)

const progressBox = document.getElementById('progress-box')
const cancelBox = document.getElementById('cancel-box')
const cancelBtn = document.getElementById('cancel-btn')
const csrf = document.getElementsByName('csrfmiddlewaretoken')

document.getElementById("upload-form").addEventListener("submit", function(submit){
    submit.preventDefault()
    progressBox.classList.remove('not-visible')
    cancelBox.classList.remove('not-visible')

    const fd = new FormData()
    fd.append('csrfmiddlewaretoken', csrf[0].value)
    fd.append("acte_propriete", document.getElementById("id_acte_propriete").files[0])
    fd.append("carte_identite", document.getElementById("id_carte_identite").files[0])
    fd.append("diagnostic_amiante", document.getElementById("id_diagnostic_amiante").files[0])
    fd.append("diagnostic_assainissement", document.getElementById("id_diagnostic_assainissement").files[0])
    fd.append("diagnostic_electricite", document.getElementById("id_diagnostic_electricite").files[0])
[...]

    $.ajax({
       type:'POST',
       url: uploadForm.action,  
       enctype: 'multipart/form-data',
       data: fd,
       beforeSend: function(){

       },
       xhr: function(){
            const xhr = new window.XMLHttpRequest();
            xhr.upload.addEventListener('progress', e=>{
                // console.log(e)
                if(e.lengthComputable){
                    const percent = e.loaded / e.total * 100
                    console.log(percent)
                    progressBox.innerHTML = `<div class="progress">
                                             <div class="progress-bar" role="progressbar" style="width: ${percent}%" aria-valuenow="${percent}" aria-valuemin="0" aria-valuemax="100"></div>
                                             </div>
                                             <p>${percent.toFixed(1)}%`
                }
            })
            cancelBtn.addEventListener('click', ()=>{
                xhr.abort()
                progressBox.innerHTML=""
                cancelBox.classList.add('not-visible')
            })
            return xhr
       },
       success: function(response){
            console.log(response)
            cancelBox.classList.add('not-visible')
       },
       error: function(error){
            console.log(error)
       },
       cache: false,
       contentType: false,
       processData: false,
    })
})

Когда я перехожу на форму, где я ранее загрузил два документа, и ставлю два флажка, чтобы очистить файлы, вот результаты печати request.POST и request.FILES:

использование submit без ajax: (вырезая часть, мы видим, что QueryDict имеет некоторые "id_document"_clear со значениями "on")

<QueryDict: {'csrfmiddlewaretoken': ['sXsUcg59BinrfOhBT56G33BltdETPflLSYTnM0XWOETevBTQpNkZhA42T8EisVha'], 'acte_propriete-clear': ['on'], 'acte_propriete': [''], 'carte_identite': [''], 'diagnostic_amiante-clear': ['on'], 'diagnostic_amiante': [''], 'diagnostic_assainissement': [''], 'diagnostic_electricite': [''], [...]>
<MultiValueDict: {}>

использование ajax: (QueryDict имеет все на 'Undefined')

>
<QueryDict: {'csrfmiddlewaretoken': ['UeUDIIIRxXxl1VWr3PRN5igRLTdC5vbskfl6isAEKj38hIyGzx56jPJybOd1Ib7R'], 'acte_propriete': ['undefined'], 'carte_identite': ['undefined'], 'diagnostic_amiante': ['undefined'], 'diagnostic_assainissement': ['undefined'], 'diagnostic_electricite': ['undefined'], [...]>
<MultiValueDict: {}>

Как бы вы сделали так, чтобы это работало?

Вернуться на верх