在Django框架下上传未知数量(动态确定)的文件

时间:2019-01-09 09:14:52

标签: python jquery ajax django

我遇到了一个问题:如果我想通过添加引导程序代码来动态地应用此行(请参阅bootstrap),则我将不知道用户会预先上传多少个文件。(尽管我定义了最大允许上传的文件数:10) 我正在使用Django 2.1.5。 我试图在form.py中编写类似UploadFileForm的内容,但是那样,我需要在类中准确地编写 10 form.Charfield ,这是我不愿看到的。

<form action="" method="post" enctype="multipart/form-data" id="bookform">
    {% csrf_token %}
    <table id="createBookTable" class=" table order-list">
        <thead>
            <tr>
                <td>book title(in original lang.)</td>
                <td>author(in original lang.)</td>
                <td>book title(in Eng.)</td>
                <td>author(in Eng.)</td>
                <td>book image</td>
            </tr>
        </thead>
        <tbody>
              <tr style="display:none">
                <td colspan="5" style="text-align: left;" >
                    <input type="text" id="counter" name="counter" value=""/>
                </td>

            </tr>
            <tr class="bookTr" id="bookTr-0">
                <td class="col-sm-3">
                    <input type="text" name="orginBookname0" class="form-control" />
                </td>
                <td class="col-sm-3">
                    <input type="mail" name="originAuthor0"  class="form-control"/>
                </td>
                <td class="col-sm-3">
                    <input type="text" name="engBookname0"  class="form-control"/>
                </td>
                <td class="col-sm-3">
                    <input type="text" name="engAuthor0"  class="form-control"/>
                </td>
                <td>
                    <input type="file" name="bookimg0">
                </td>
                <td class="col-sm-1"><a class="deleteRow"></a>

                </td>

            </tr>

        </tbody>
        <tfoot>

            <tr>
                <td colspan="5" style="text-align: left;">
                    <input type="button" class="btn btn-lg btn-block " id="addrow" value="Add Row" />
                </td>
            </tr>
              <tr>
                <td colspan="5" style="text-align: left;">
                    <input  type="submit" name="button" id="bookSubmitBtn" class="btn btn-lg btn-block btn-beautiful" value="Submit">
                </td>
            </tr>
        </tfoot>
    </table>
</form>

这些是上述引导程序演示示例的修改版本:

var counter = 0;
$("#counter").prop('value',counter);
$("#addrow").on("click", function () {

    if(counter<=9){
        counter++;
        var newRow = $('<tr class="bookTr" id="bookTr-'+counter+'">');
        var cols = "";

        cols += '<td><input type="text" class="form-control" name="orginBookname' + counter + '"/></td>';
        cols += '<td><input type="text" class="form-control" name="originAuthor' + counter + '"/></td>';
        cols += '<td><input type="text" class="form-control" name="engBookname' + counter + '"/></td>';
        cols += '<td><input type="text" class="form-control" name="engAuthor' + counter + '"/></td>';
        cols += '<td><input type="file" name="bookimg' + counter + '"/></td>';
        cols += '<td><input type="button" class="ibtnDel btn btn-md btn-danger "  value="Delete"></td>';
        newRow.append(cols);
        $("table.order-list").append(newRow);

        $("#counter").prop('value',counter);
    }
    else{
        alert("You can only add 10 books per time.");
    }
});

预期结果是将用户选择的所有文件上载到media \ photos文件夹。同样,我们无法预先知道它们将上传多少文件。 我想在Django框架下的前端使用ajax调用。

2 个答案:

答案 0 :(得分:0)

我认为您正在寻找表单集。您可以使用django formset动态呈现和上传任意数量的表单字段。在这里https://github.com/elo80ka/django-dynamic-formset

中查看

答案 1 :(得分:0)

我找到了一种避免使用form.py而是使用ajax调用的方法。 在settings.py

MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

在urls.py

urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

在models.py

class book(models.Model):
    titleOrigin = models.CharField(max_length=200,null = False)
    authorOrigin = models.CharField(max_length=100,null = True)
    titleEnglish = models.CharField(max_length=200,null = True)
    authorEnglish = models.CharField(max_length=100,null = True)
   bookImgFname = models.CharField(max_length=300,null=True)

在createbook.js中(使用 FormData()函数!!!):

function upload(event) {
    event.preventDefault();
    var formdata = new FormData($('#bookform').get(0));
    $.ajax({
            url: '/createbook/',
            type: 'post',
            data: formdata,
            cache: false,
            processData: false,
            contentType: false,
            success: function(data) {
                alert('success');
            }
        });
   return false;
}
$(function() {
    $('#bookform').submit(upload);
});

在views.py中,使用 FileSystemStorage request.FILES ['bookimg'+ str(i)] (感谢this tutorial

def createbook(request):
   if request.method == 'POST' and request.is_ajax():

      for i in range(int(request.POST.get('counter'))+1): **#the nondisplayed counter is a trick**

         curOrginBookname = request.POST.get('orginBookname'+str(i))
         curOriginAuthor = request.POST.get('originAuthor'+str(i))
         curEngBookname = request.POST.get('engBookname'+str(i))
         curEngAuthor = request.POST.get('engAuthor'+str(i))
         curBookimg = request.FILES['bookimg'+str(i)]
         fss = FileSystemStorage()
         concatenatedFname = curOrginBookname+"_"+curBookimg.name
         fss.save("photos\\"+concatenatedFname, curBookimg)
         bookToBeSaved = book(titleOrigin=curOrginBookname,authorOrigin=curOriginAuthor,
                              titleEnglish=curEngBookname,authorEnglish=curEngAuthor,bookImgFname=concatenatedFname)
         bookToBeSaved.save()


      return HttpResponse('')

   else:

      return render(request, "createbook.html", locals())

记住要导入:

from django.core.files.storage import FileSystemStorage