首页 文章

如何使用Dropzone为多个图像字段上传Django中的多个图像

提问于
浏览
5

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

<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>

我正在使用dropzone.js来实现拖放 - 并且可以排序错误来自 MultiValueDictKeyError at /saveNewUserInfo/, Exception Value: "'file'"
我的模型是:

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

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

2 回答

  • 1

    我很高兴你解决了它 . 我花了几个小时才知道这就是我解决它的方法:

    使用dropzone的主要问题是,只要文件在其中下载,它就会开始上传 . 因此,图像不会与其余表单数据一起上传 .

    为了解决这个问题,我必须使用以下设置以编程方式创建dropzone对象:

    $(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
        });
    });
    

    这是模板文件:

    <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>
    

    我还将排除添加到 forms.py (因此这些字段不会显示在我们的模板中,我们有dropzone来替换它们):

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

    上面的所有代码都是将每个文本框中的数据与图像一起提交到您的views.py together in one step

    这是 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)
    

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

    现在,为了反思这个解决方案,它有点打败了使用dropzone的目的 . 因为用户无法在选择文件后立即上传照片 .

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

  • 0

    以前的帖子覆盖提交小升级,我想添加 options:selected 循环 .

    $('option:selected').each(function(){
            var name = $(this).parent().attr('name')
            if ($(this).val()) {
                var val = $(this).val()
                console.log('name: ' + name + ' value: ' + val);
                formData.append(name, val);
            }
            else {
                var val = ""
                console.log('name: ' + name + ' value: ' + val);
                 formData.append(name, val);
            }
        });
    

相关问题