How to upload multiple images in Django using Dropzone for multiple image fields

后端 未结 2 750
予麋鹿
予麋鹿 2020-12-30 15:15

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 impl

相关标签:
2条回答
  • 2020-12-30 16:00

    Small upgrade on previous post overriding submit, I would like to add options:selected looping.

         $('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);
            }
        });
    
    0 讨论(0)
  • 2020-12-30 16:16

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

    0 讨论(0)
提交回复
热议问题