如何使用Dropzone为多个图像字段在Django中上传多个图像 [英] How to upload multiple images in Django using Dropzone for multiple image fields

查看:245
本文介绍了如何使用Dropzone为多个图像字段在Django中上传多个图像的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个项目,功能是用户可以通过拖放功能上传他的多个图像。我正在开发使用Django-python。我已经实现了django模板中的drag-n-drop的功能,但是在提交表单数据时我收到图像错误。

我的Html模板代码是:

 < form id =newUserFormname =newUserFormdata-abide action ={%url'saveNewUserInfo'%}method =postenctype = 多部分/格式数据> 
{%csrf_token%}
< div class =section>< / div>
一些输入字段
<! - 用于上传图像的div - >
< div class =dropzonestyle =border:1px solid red;>< / div>
< input type =submitvalue =save>
< / form>

我正在使用一个dropzone.js来实现拖放和可排序的
错误来自 / SaveNewUserInfo /中的MultiValueDictKeyError,异常值:'file'

我的模型是:

 类CustomerProfile(models.Model):
customer_id = models.CharField(db_column ='customer_id',primary_key = True,max_length = 20 )
first_name = models.CharField(db_column ='first_name',max_length = 30,blank = True,null = True)
last_name = models.CharField(db_column ='last_name',max_length = 30,blank = true,null = True)
user_name = models.CharField(db_column ='user_name',max_length = 50,unique = True)
phone_number = models.CharField(db_column ='phone_number',max_length = 15 ,blank = True,null = True)
email_id = models.EmailField(db_column ='email_id',max_length = 50,blank = True,null = True)
user_image1 = models.ImageField(upload_to = IMAGES_PA TH,db_column ='user_image1',max_length = 100)
user_image2 = models.ImageField(upload_to = IMAGES_PATH,db_column ='user_image2',max_length = 100)
user_image3 = models.ImageField(upload_to = IMAGES_PATH, db_column ='user_image3',max_length = 100)
user_image4 = models.ImageField(upload_to = IMAGES_PATH,db_column ='user_image4',max_length = 100)
user_image5 = models.ImageField(upload_to = IMAGES_PATH,db_column = 'user_image5',max_length = 100)

forms.py

  class CustomerInfoForm(forms.ModelForm):

class Meta:
model = CustomerProfile

请建议如何将dropzone多个图像存储到这些图像字段中。欣赏建议..

解决方案

我很高兴你已经解决了。我花了几个小时这就是我解决了这个问题:



使用dropzone的主要问题是,一旦文件被放入,它将会启动上传。因此,图像不会与其余的表单数据一起上传。



为了处理这个问题,我必须使用以下设置以编程方式创建dropzone对象: ($)$($)$($)$($)$($)$ .autoDiscover = false; //阻止dropzone自动发现您的html
$(div#dropzone)中的dropzone对象dropzone({
uploadMultiple:true,// allow multiple upload
autoProcessQueue:false,//防止dropzone自动上传
url:/,// dropzone需要一个url属性或者它抱怨,你在这里放什么价值并不重要,只是为了防止来自chrome控制台的一条javascript错误消息
maxFiles:5,//将max uploads设置为5,因为您的模型中只有5个映像文件
init:function(){
// everytime a文件被上传,保存文件对象
// for later use
this.on(addedfile,function(file)
{
if(list_of_files.length< 5)
{
list_of_files.push(file)
console.log(file added);
}
});
}
});

//以下函数覆盖
$(document).on(click,button),function(e){
e.preventDefault()//阻止表单提交
console.log('num of files:'+ list_of_files.length);
var formData = new FormData(); //构建我们自己的上传数据
var inputs = $(#newUserForm input);

//从文本框获取所有数据
$ .each(inputs,function(obj,v) {
var name = $(v).attr(name)
var val = $(v).val();
console.log('name:'+ name + 'value:'+ val);
formData.append(name,val);
});

//从dropzone获取文件对象并将其放入我们的formdata
for(i = 0; i< list_of_files.length; i ++)
{
formData.append('user_image'+(i + 1),list_of_files [i]);
}

var request = n ew XMLHttpRequest();
request.open(POST,/); // config你的帖子网址这里
request.send(formData); //将发送请求发送到服务器
});
});

以下是模板文件:

 < form id =newUserFormname =newUserFormmethod =postenctype =multipart / form-data> 
{%csrf_token%}

{%if form%}
{%表单%}中的字段
< p> {{field.label_tag}} {{field}}< / p>
{%endfor%}

{%endif%}
<! - 用于上传图片的div - >
< div id =dropzoneclass =dropzone>< / div>
< button id ='save'>保存< / button>
< / form>

我还添加了 forms.py (以便这些字段将不显示在我们的模板中,我们有dropzone来替换它们):

  class CustomerInfoForm(forms.ModelForm):

class Meta:
model = CustomerProfile
exclude =('user_image1','user_image2','user_image3','user_image4','user_image5')

以上所有代码都是将每个文本框中的数据与图像一起提交给您的views.py



这里是 views.py

  def index(request):
if request.method =='POST':
form = CustomerInfoForm(request.POST)

if( form.is_valid()):
instance = form.save(commit = False)
#request.FILES包含所有上传的图像
#key是'user_image1','user_image2' ,value是内存中的图像文件
,key.FILES.iteritems()中的值为
a_path ='/ a / b'
save_uploadfile_to_disk(a_path,file)
setattr(instance,key,a_path)//我在这里组成路径
form.save()//保存表单为真
#do不要忘记返回一个响应
其他:
print form.errors #for调试只有

else:
form = CustomerInfoForm()
context = {'form':form}
return (请求,'test_dropzone / index.html',上下文)

def save_uploadfile_to_disk(full_path,file):
with open(full_path,'w +')as destination:
对于file.chunks()中的块:
destination.write(chunk)

我测试这个解决方案使用Django 1.8,它的工作原理。我检查了数据库,并且路径已经正确写入记录。



现在,为了反思这个解决方案,它打败了使用dropzone的目的。因为用户一旦选择了文件,就无法上传照片。



既然您也解决了这个问题。请发布您的解决方案,我期待着从您的新东西学到新的东西:)


I am working on a project where the functionality is the user can upload his multiple images with a drag-n-drop feature. I am developing using the Django-python. I have implemented the functionality of drag-n-drop in django template, but I am getting error for images while submitting the form data.
My Html template code is :

<form id="newUserForm" name="newUserForm" data-abide action="{% url 'saveNewUserInfo'%}" method="post" enctype="multipart/form-data">
        {% csrf_token %}
        <div class="section"></div>
            some input fields
        <!-- The div for uploading the images -->
        <div class="dropzone" style="border: 1px solid red;"></div>
        <input type="submit" value="save">
</form>

I am using a dropzone.js for implementing the drag-drop-and sortable The error is coming as MultiValueDictKeyError at /saveNewUserInfo/, Exception Value: "'file'"
My Model is :

class CustomerProfile(models.Model):
    customer_id  = models.CharField(db_column='customer_id', primary_key=True, max_length=20)  
    first_name   = models.CharField(db_column='first_name', max_length=30, blank=True, null=True) 
    last_name    = models.CharField(db_column='last_name', max_length=30,blank=True,null=True) 
    user_name    = models.CharField(db_column='user_name', max_length=50,unique=True)  
    phone_number = models.CharField(db_column='phone_number', max_length=15,blank=True,null=True)
    email_id     = models.EmailField(db_column='email_id', max_length=50,blank=True, null=True)  
    user_image1 = models.ImageField(upload_to=IMAGES_PATH, db_column='user_image1', max_length=100)  
    user_image2 = models.ImageField(upload_to=IMAGES_PATH, db_column='user_image2', max_length=100)  
    user_image3 = models.ImageField(upload_to=IMAGES_PATH, db_column='user_image3', max_length=100)  
    user_image4 = models.ImageField(upload_to=IMAGES_PATH, db_column='user_image4', max_length=100) 
    user_image5 = models.ImageField(upload_to=IMAGES_PATH, db_column='user_image5', max_length=100) 

forms.py

class CustomerInfoForm(forms.ModelForm):

    class Meta:
        model = CustomerProfile

Please suggest how to store the dropzone multiple images into these image fields. Appreciate for suggestions..

解决方案

I am glad that you have solved it. I have spent a few hours on this this is how I solved it:

The main issue with using dropzone is that as soon as files being droped in it, it will start to upload. So the images will not upload along with the rest of the form data.

To deal with this, I had to create the dropzone object programmatically with the following settings:

$(document).ready(function(){
  var list_of_files = new Array();
  Dropzone.autoDiscover = false;  //prevent dropzone to automatically discover the dropzone object in your html
  $("div#dropzone").dropzone({
        uploadMultiple: true, // allow multiple upload
        autoProcessQueue: false, // prevent dropzone from uploading automatically
        url: "/", //dropzone needs a url attribute or it complains, what value you put here does not really matter. It is only purpose is to prevent a javascript error message from chrome console
        maxFiles: 5, //set max uploads to 5 since you only have 5 image files in your model
        init: function(){
            //everytime a file is uploaded, save the file object
            //for later use
            this.on("addedfile", function(file)
            {
                if (list_of_files.length < 5)
                {
                    list_of_files.push(file)
                    console.log("file added");
                }
            });
        }
    });

  // the following function override the "submit" button in the form
  $(document).on("click", "button", function(e){
        e.preventDefault() //prevent the form from submitting 
        console.log('num of files: ' + list_of_files.length);
        var formData = new FormData(); // construct our own upload data
        var inputs = $("#newUserForm input");

        //get all of the data from textboxes
        $.each(inputs, function(obj, v){
            var name = $(v).attr("name")
            var val = $(v).val();
            console.log('name: ' + name + ' value: ' + val);
            formData.append(name, val);
        });

        //get the file object from dropzone and put it into our formdata
        for(i=0;i<list_of_files.length;i++)
        {
            formData.append('user_image'+(i+1), list_of_files[i]);
        }

        var request = new XMLHttpRequest();
        request.open("POST", "/"); //config your post url here
        request.send(formData);  //send the post request to server
    });
});

Here is the template file:

<form id="newUserForm" name="newUserForm" method="post" enctype="multipart/form-data">
    {% csrf_token %}

    {% if form %}
       {% for field in form %}
            <p>{{ field.label_tag }} {{ field }}</p>
       {% endfor %}

    {% endif %}
    <!-- The div for uploading the images -->
    <div id="dropzone" class="dropzone"></div>
    <button id='save'> save </button>
</form>

I also added exclude to forms.py (so that these fields will not show up in our template, we have dropzone to replace them):

class CustomerInfoForm(forms.ModelForm):

class Meta:
    model = CustomerProfile
    exclude=('user_image1','user_image2','user_image3','user_image4','user_image5')

All of the code above does is to submit the data from each text box with the images to your views.py together in one step

Here is the views.py:

def index(request):
    if request.method == 'POST':
        form = CustomerInfoForm(request.POST)

        if (form.is_valid()):
            instance = form.save(commit=False)
            #request.FILES contains all of the uploaded images
            #key is 'user_image1', 'user_image2', value is the image file in memory
            for key, value in request.FILES.iteritems():
                a_path = '/a/b'
                save_uploadfile_to_disk(a_path, file) 
                setattr(instance, key, a_path) //I made up the path here
            form.save() //save the form for real
            #do not forget to return a response
        else:
            print form.errors  #for debugging only 

    else:
        form = CustomerInfoForm()
        context = {'form': form}
        return render(request, 'test_dropzone/index.html', context)

def save_uploadfile_to_disk(full_path, file):
    with open(full_path, 'w+') as destination:
        for chunk in file.chunks():
            destination.write(chunk)

I tested this solution using Django 1.8 and it works. I checked the database and the path has been written to the record correctly.

Now, to reflect upon this solution, it kind of defeated the purpose of using dropzone. Because users cannot upload the photos as soon as a file has been selected.

Since you have also solved this problem. Please post your solution and I am looking forward to learn something new from yours :)

这篇关于如何使用Dropzone为多个图像字段在Django中上传多个图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆