javascript - Django 和 Dropzone.js

标签 javascript python django file-upload dropzone.js

当我使用 dropzone 上传文件时,它会将它们添加到数据库中,但它们没有文件,只有 ID 和创建日期。我认为观点是问题所在,但我已经尝试了很多东西,但我无法弄清楚。有关更详细的说明,请参阅下面我的编辑。

这是 View

@login_required(login_url='/dashboard-login/')
def dashboard(request):
    current_user = request.user
    current_client = request.user.client

    files = ClientUpload.objects.filter(client=current_client)

    form = UploadFileForm()

    if request.method == 'POST':
        if request.FILES is None:
            logger = logging.getLogger(__name__)
            logger.warning("No files were attached to the upload.")
            return HttpResponseBadRequest('No Files Attached.')

        if form.is_valid():
            upload = form.save()
            form = UploadFileForm(request.POST, request.FILES)

        else:
            uploaded_files = [request.FILES.get('file_upload[%d]' % i)
                for i in range(0, len(request.FILES))]

            for f in uploaded_files:
                client_upload = ClientUpload.objects.create(client=current_client, file_upload=f)

            #for key in request.FILES:
            #    cupload = ClientUpload.objects.create(client=current_client, file_upload=request.FILES[key])

        logger = logging.getLogger(__name__)
        logger.debug(request.FILES)
        logger.info("File(s) uploaded from " + current_client.company)          

        return HttpResponseRedirect(reverse('dashboard'))

    data = {'form': form, 'client': current_client, 'files': files}
    return render_to_response('dashboard.html', data, context_instance=RequestContext(request))

这是我的 dz 选项:

url: '127.0.0.1:8003/dashboard/',
      method: "post",
      withCredentials: false,
      parallelUploads: 12,
      uploadMultiple: true,
      maxFilesize: 256*4*2,
      paramName: "file_upload",
      createImageThumbnails: true,
      maxThumbnailFilesize: 20,
      thumbnailWidth: 100,
      thumbnailHeight: 100,
      maxFiles: 12,
      params: {},
      clickable: true,
      ignoreHiddenFiles: true,
      acceptedFiles: null,
      acceptedMimeTypes: null,
      autoProcessQueue: false,
      addRemoveLinks: true,
      previewsContainer: null,
      dictDefaultMessage: "Drop files here to upload",
      dictFallbackMessage: "Your browser does not support drag and drop file uploads.",
      dictFallbackText: "Please use the fallback form below to upload your files.",
      dictFileTooBig: "File is too big ({{filesize}}MB). Max filesize: {{maxFilesize}}MB.",
      dictInvalidFileType: "You can't upload files of this type.",
      dictResponseError: "Server responded with {{statusCode}} code.",
      dictCancelUpload: "Cancel upload",
      dictCancelUploadConfirmation: "Are you sure you want to cancel this upload?",
      dictRemoveFile: "Remove",
      dictRemoveFileConfirmation: null,
      dictMaxFilesExceeded: "You can only upload {{maxFiles}} files.",

这是模板:

{% load i18n %}
{% load staticfiles %}
{% load crispy_forms_tags %}

<link href="{% static 'css/dropzone2.css' %}" type="text/css" rel="stylesheet"/>

<form class="dropzone" id="myDropzone" method="post" action="{% url 'dashboard' %}" enctype="multipart/form-data">
    {% csrf_token %}
    <div class="fallback">
        <input name="file" type="file" multiple />
    </div>  
</form>
<button class="upload-control btn-success btn" type="submit" id='submit-all' onclick="document.getElementById('myDropzone').submit()">
    <i class="glyphicon glyphicon-upload"></i>
    <span>{% trans 'Submit' %}</span>
</button>

<style>
    .upload-control {
        margin-top: 10px;
        margin-bottom: 0px;
    }
</style>
<script src="{% static 'js/dropzone.js' %}"></script>
<script src="{% static 'js/jquery-2.1.4.min.js' %}"></script>
<script type="text/javascript">
    Dropzone.autoDiscover = false
    $(document).ready(function() {
        Dropzone.options.myDropzone = {

            init : function() {
                var submitButton = document.querySelector("#submit-all")
                myDropzone = this;

                submitButton.addEventListener("click", function(e) {
                    e.stopPropagation();
                    e.preventDefault();
                    myDropzone.processQueue();
                });

                this.on("sendingmultiple", function() {
                    // Figure out what I want here or if I want at all
                });

                this.on("successmultiple", function(files, response) {
                    window.location.reload();
                });

                this.on("errormultiple", function(files, response) {
                    // Figure out what I want here or if I want at all
                });

                }
                // Do I need this?
                //myDropzone.on('success', myDropzone.processQueue.bind(myDropzone));
        };
});    
</script>

编辑:

在将 http://添加到 url 设置后,它现在可以工作了。但是当我上传一个文件时,它被添加到数据库中,但是文件字段是空白的。多值字典在我打印出来时显示文件,但是当它保存到数据库时,文件字段中没有任何内容。

当我上传一个文件时,我会在请求中得到这个文件。文件:

<MultiValueDict: {u'file_upload[]': [<InMemoryUploadedFile: normal.PNG (image/png)>]}>

当我上传两个时,我在请求中得到了这个。文件:

<MultiValueDict: {u'file_upload[]': [<TemporaryUploadedFile: normal.PNG (image/png)>]}>

尽管是两个文件,它只显示一个文件,但将它们都添加到数据库中(都没有文件,只有 ID 和创建日期)。还有什么是 TemporaryUploadedFile 和 InMemoryUploadedFile?

当我上传多个但它没有时,它应该在 u'file_upload[]' 中有索引。我的设置正确,可以上传多个。

但我似乎无法将它们从 MultiValueDict 中取出。当我尝试类似的东西时:

for upload in request.FILES:
    client_upload = ClientUpload.objects.create(client=current_client, file_upload=upload)

我遇到了管理面板显示 ID 和时间但没有文件的问题。上传一个或多个时会发生这种情况。我也不确定 InMemoryUploadedfile 和 TemporaryUploadedFile 之间有什么区别。如何从 MultiValueDict 中提取文件? get() 不起作用,使用列表 comp 我只得到一个空列表。

另一件奇怪的事情是,当我上传某些文件时,MultiValueDict 是空的,而其他文件则不是。此外,似乎我的 View 被调用不止一次(根据日志输出),这是正常的,除了它应该是一个帖子然后重定向到一个 get,但它似乎有不止一个帖子请求。我检查了 chrome 中的开发工具,我只看到一个,但奇怪的是,每次提交时它都会输出我的日志语句两次。我知道这个问题可能在我看来,但我已经尝试了很多东西,但无法弄清楚哪里出了问题。

有人有什么想法吗?

最佳答案

我自己正在使用 Dropzone 和 Django 为每个上传的文件创建 Image 对象,这似乎类似于您想要做的。我想指出一些我经历过的事情,并向您展示我是如何做的,看看是否有帮助。

你需要什么

为了在数据库中为使用 Dropzone 上传的文件创建记录,您需要的是:

  1. Dropzone HTML 表单
  2. Dropzone 的 Javascript 初始化。
  3. 处理上传文件的 Django View 。

我不明白你在用表单做什么(它只是验证吗?)但它似乎是不必要的。您不需要(也不要使用它)来实际保存文件。

访问上传的文件

首先让我们谈谈如何访问request.FILES中的文件。 .通过设置 uploadMultiple: true在您的 Dropzone 配置上,您要求 Dropzone 不发送 dzfile但要发送表示为 dzfile[%d] 的每个文件(即 dzfile[0]dzfile[1] 等)。

即使情况并非如此,您使用 request.FILES 就像它是一个列表 ( for f in request.FILES ),但就像您指出的那样,它实际上是一个字典。

这是我打印 request.FILES 时 Python 显示的内容:

<MultiValueDict: {u'dzfile[1]': [<InMemoryUploadedFile: image2.jpg (image/jpeg)>], u'dzfile[2]': [<InMemoryUploadedFile: image3.jpg (image/jpeg)>], u'dzfile[0]': [<InMemoryUploadedFile: image1.jpg (image/jpeg)>]}>

要访问您需要的实际文件 get 每个键都有它的名字。

files = [request.FILES.get('dzfile[%d]' % i)
     for i in range(0, len(request.FILES))]

现在您有了所需的文件列表。只需遍历它并根据需要创建对象。我不确定您的模型是如何工作的,所以我将进行近似。

for f in files:
    # Create a ClientUpload object by setting its FK to client and
    # FileField to the file. Correct me if I deduced the models incorrectly
    client_upload = ClientUpload.objects.create(
        client=current_client,
        file_upload=f,
    )

这应该足以创建您想要的对象。

Dropzone Javascript

看来在你添加到提交按钮的Click事件监听器中你必须添加

e.preventDefault();
e.stopPropagation();

在调用 processQueue() 之前避免双重表单提交。

至于sendingmultiple , successmultipleerrormultiple ,你想在那里发生什么?注释仅用于指示何时触发这些事件。

我个人使用:

this.on('sendingmultiple', function () {
    // `sendingmultiple` to hide the submit button
    $('#my-dropzone').find('button[type=submit]').hide();
});
this.on('successmultiple', function (files, response) {
    // `successmultiple` to reload the page (and show the updated info)
    window.location.reload();
});
this.on('errormultiple', function (files, response) {
    // `errormultiple` to un-hide the button
    $('#my-dropzone').find('button[type=submit]').show();
});

当然你可以做你想做的。

最后,您打算在 <script> 中的最后一行发生什么?标签?我不是很明白,看起来如果你想在成功时重新处理队列。它似乎不属于那里。

如果有任何问题请评论,但此设置对我来说工作正常。

关于javascript - Django 和 Dropzone.js,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31949863/

相关文章:

javascript - 响应式导航在页面加载时打开然后隐藏。应该在页面加载时隐藏

javascript - jQuery 模板不显示数据元素

python - 如何在Scrapy spider中获取pipeline对象

python - 在python列表中对元组进行排序

Javascript不会在django的表单集隐藏输入字段中插入值

python - 如何使用 SHELL_PLUS_DONT_LOAD? django-extensions==1.6.1, Django==1.9.2

javascript - 如何使 JSON 数据只能由我的 java 脚本访问?

javascript - 任何图表。如何添加|删除标记?

python - 根据 ID 和月份聚合数据,具体取决于另一列(前与后)

mysql - 模块未找到错误 : No module named 'MySQLdb' with django 1. 10.5