0

I'm trying to handle file upload in Django from Ajax post, it doesn't work :(

Below is the code in html file which does the upload :

<form action="{% url 'saveprof' %}" method="post" enctype="multipart/form-data" id="form1">
        {% csrf_token %}
        <div class="profpic" style="background:url(../../../static/app/img/profile.png)">
            <input type="file" id="picpath" name="picpath" class="uploadpic" value=""/>
        </div>
        </form>            
        {% csrf_token %}

Save

Below Ajax method is used to post the data :

function saveprof() {
var formData = {
                'picpath_Aj': $('#picpath').val()
            };
        $.ajax({
            type: "POST",
            url: "saveprof",
            enctype: 'multipart/form-data',
            async: true,
            data: {
                 formData,
                'profemail_Aj': $('#profemail').val(),
                'csrfmiddlewaretoken': $("input[name=csrfmiddlewaretoken]").val()
            },
            success: function (data, textStatus, jqXHR) {
                $('#message').html(data);
            }
        });
    }

Is this possible ?

How can I use html form for File upload and send this data via above ajax method ?

Here is the view

def saveprof(request):
    if request.method == "POST":
        user_form1 = DocumentForm(request.POST, request.FILES)
        if user_form1.is_valid():
            user_form1.save()
    #And code to save some other fields as well along with the user_form1

Form.py

class DocumentForm(forms.ModelForm):
    picpath = forms.FileField()
    class Meta:
        model = td_Student
        fields = ('picpath',)

Model.py

class td_Student(models.Model):
    picpath=models.FileField(upload_to=unique_filename)

def unique_filename(instance, filename):
    ext = filename.split('.')[-1]
    filename = "%s_%s.%s" %(uuid.uuid4(),time.strftime("%Y%m%d_%H%M%S"), ext)
    return os.path.join('documents/documents/'+time.strftime("%Y%m%d"), filename

When this code is being ran, user_form1.save() never gets executed as it is failing validity condition in the view.

I tried for several hours to figure out the issue, but couldn't get. Could you please help me in identifying what is wrong with this implementation in view ?

Image is not being saved in the server :(.. and I couldn't get the file name as expected (Example : 'documents/documents/20150716/a1f81a80-ce6f-446b-9b49-716b5c67a46e_20150716_222614.jpg' as per unique_filename method )

Please note that I can successfully upload image when I use HTML form instead of using Ajax post.. but my requirement for current implementation is Ajax only.

Satheesh Panduga
  • 818
  • 2
  • 13
  • 32
  • one possible easy way to find what's not validating is `print form.errors` when not `is_valid` – Raja Simon Jul 17 '15 at 05:00
  • Hi Raja, I used it already, Error is, 'the field picpath is required'.. It looks like picpath is not being sent to my view by the Ajax method. value of picpath is wrong (for any image that is uploaded, it shows something like 'c:\fakepath\imagename.jpg' ) – Satheesh Panduga Jul 17 '15 at 06:19
  • Can you print `request.POST` in `saveprof` view? Seems like you ain't sending any value with `picpath` key. – Ernest Jul 17 '15 at 06:49

1 Answers1

3

We say you have a form like this:

<form method="POST" name="form" id="form" enctype="multipart/form-data">
    <input type="file" id="img"/>
    <input type="submit"/>
</form>

you have to get the img chosen by the user so your javascript have to look like this:

$(document).ready(function(){
    $('form').on('submit', function(e){
        e.preventDefault();
        var data = new FormData($('form').get(0));
        $.ajax({
            url: :"/URL",
            method: "POST",
            data: data,
            success: function(data){},
            error: function(data){},
            processData: false,
            contentType: false,
        });
    });
});

and now you are going to be able to retrieve the img chosen by the user in django with:

request.FILES
Navneet
  • 4,543
  • 1
  • 19
  • 29