使用 XMLHttpRequest 的 django 文件上传进度条

django file upload progress bar with XMLHttpRequest

我创建了一个普通的 django model.ModelForm 并且它运行良好,直到我尝试为文件上传添加进度条,我遇到了问题。我收到了两次表格信息(request.POST 和 request.FILES)!但它只在数据库中保存一次数据,所以它也可以工作,但我知道我的代码有错误,我想了解我的错误。

这是我显示进度条的函数:

function UploadFilesWithProgress(form, url) {
    const progressbarWrap = document.querySelector('.progress-bar-wrap'),
         label = progressbarWrap.querySelector('h6'),
         percentage = progressbarWrap.querySelector('span'),
         progressbarFill = progressbarWrap.querySelector('.progress > .progress-bar')

    let xhr = new XMLHttpRequest()

    xhr.open('POST', url, true);
    xhr.upload.onloadstart = function (e) {
        progressbarWrap.classList.remove('d-none')
        percentage.textContent = '0%'
        label.textContent = 'uploading...'
    };

    xhr.upload.onprogress = function (e) {
        const percent = e.lengthComputable ? (e.loaded / e.total) * 100 : 0;
        progressbarFill.style.width = percent.toFixed(2) + '%';
        progressbarFill.setAttribute('aria-valuenow', percent.toFixed(2))
        percentage.textContent = percent.toFixed(2) + '%';
    }

    xhr.upload.onloadend = function (e) {
        label.textContent = 'uplaod completed!'
        percentage.textContent = 'completed!'
    }
    xhr.send(new FormData(form));
}

Form = document.getElementById('add-course-form')
if (Form) {
    Form.onsubmit = function () {
    UploadFilesWithProgress(Form, Form.action); 
    }
}

这是我的观点:

        # I use CBV, so i share just the post method to not get missy.

        def post(self, *args, **kwargs):
            form = OfflineTutorialForm(
            user=self.request.user.booth,
            data=self.request.POST,
            files=self.request.FILES
            )
            video_formset = AddOfflineVideoTutorialFormSet(
            data=self.request.POST,
            files=self.request.FILES
            )

           print(self.request.POST, self.request.FILES)
           if form.is_valid() and video_formset.is_valid():
               off_tutorial = form.save(commit=False)
               off_tutorial.booth = self.request.user.booth
               off_tutorial.save()
               form.save_m2m()
               video_off_tutorial = video_formset.save(commit=False)
               for video in video_off_tutorial:
                   video.tutorial = off_tutorial
                   video.save()
           return redirect('offline-tutorial')
       return redirect('/')

看来您是通过表单提交上传数据,ajax,您可以通过event.preventDefault()

阻止表单正常提交
Form.onsubmit = function (event) {
    event.preventDefault();
    UploadFilesWithProgress(Form, Form.action); 
}