0

I am new in web development.I want to upload a file and process it in a Celery task and show progress percent using AJAX. I used some samples like this and here is my code:

views.py:

def importnewdata(request):

    if request.method == 'POST':
        form = RawFileAddressForm(request.POST, request.FILES)
        if form.is_valid():
            file = request.FILES['file']
            file_name = default_storage.save("sample.txt", file)
            task = process_file.delay(file_name)
            return HttpResponse(json.dumps({'task_id': task.id}), content_type='application/json')
        else:
            return HttpResponse("Error1!")
    else:

        form = RawFileAddressForm()
        return render(request, 'modelmanager/importnewdata.html', {'form': form})



def get_task_info(request):
    task_id = request.GET.get('task_id', None)
    if task_id is not None:
        task = AsyncResult(task_id)
        data = {
            'state': task.state,
            'result': task.result,
        }
        return HttpResponse(json.dumps(data), content_type='application/json')
    else:
        return HttpResponse('No job id given.')

forms.py:

class RawFileAddressForm(forms.Form):
    file = forms.FileField()

importnewdata.html:

<!DOCTYPE html>
<html>
<head>
    <title>import new raw data to db</title>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>

</head>
<body style="text-align: center;">

    <h1>select your file to process it!</h1>
    <progress id="progress-bar" value="0" max="100" style="display:none; margin-bottom: 1em;"></progress>

    <form id="process-raw-data" action="/modelmanager/importnewdata/" method="post" enctype="multipart/form-data">
        {% csrf_token %}
        {{  form  }}
        <input type="submit" value="Submit"/>
    </form>

<script type="text/javascript">
    var frm = $('#process-raw-data');
    var pgrbar = $('#progress-bar');

    frm.submit(function () {
        $.ajax({
            type: frm.attr('method'),
            url: frm.attr('action'),
            data: frm.serialize(),
            success: function (data) {
                if (data.task_id != null) {
                    get_task_info(data.task_id);
                }
            },
            error: function (data) {
                frm.html("error!");
            }
        });
        return false;
    });

    function get_task_info(task_id) {
        $.ajax({
            type: 'get',
            url: '/modelmanager/get-task-info/',
            data: {'task_id': task_id},
            success: function (data) {
                frm.html('');
                if (data.state == 'PENDING') {
                    frm.html('Please wait...');
                }
                else if (data.state == 'PROGRESS') {
                    pgrbar.css('display', 'inline');
                    pgrbar.val(data.result.percent);
                    frm.html('lines processed ' + data.result.current + ' out of ' + data.result.total);
                }
                else if(data.state == 'SUCCESS'){
                    pgrbar.css('display', 'none');
                    frm.html('Successfully Completed!');

                }
                if (data.state != 'SUCCESS') {
                    setTimeout(function () {
                        get_task_info(task_id)
                    }, 500);
                }
            },
            error: function (data) {
                frm.html("error!");
            }
        });
    }
</script>


</body>
</html>

The problem is after click on submit button nothing happens. I got:

"POST /modelmanager/importnewdata/ HTTP/1.1" 200 10

In Wireshark I saw

error1!

in response. It means form is not valid, but when I remove JS part from html file it returns a json object with successfully created celery task id. That means form is valid. any helps. thanks.

4
  • 2
    Don't make your input a submit within a form--that is triggering a form submit that is being triggered even after you make the ajax call. Make it a button, or prevent the default form submission in the submit handler. Commented Oct 16, 2019 at 14:22
  • @2ps thanks. but how to prevent it? please answer to accept it. Commented Oct 16, 2019 at 14:27
  • make the input a button and call the ajax from an onclick handler, not from a submit handler? Commented Oct 16, 2019 at 14:28
  • @2ps I did it like this ` $(function () { $('#mybtn').on('click', function () { $.ajax({ }); }); });` on <input id="mybtn" type='button' value='Upload'> ... but problem not solved! Commented Oct 16, 2019 at 14:42

1 Answer 1

2

Thanks to all. You helped me a lot! :)

Finally here is my solution:

views.py:

def importnewdata(request):

    cntx = {}
    if request.method == 'POST':
        form = RawFileAddressForm(request.POST, request.FILES)
        if form.is_valid():
            file = request.FILES['file']
            file_name = default_storage.save("sample.txt", file)
            task = process_file.delay(file_name)
            cntx['task_id'] = task.id
            return render(request, 'modelmanager/importnewdata.html', cntx)
        else:
            return render(request, 'modelmanager/importnewdata.html', {'form':form})
    else:

            form = RawFileAddressForm()
            return render(request, 'modelmanager/importnewdata.html', {'form': form})

def get_task_info(request):
    task_id = request.GET.get('task_id', None)
    if task_id is not None:
        task = AsyncResult(task_id)
        data = {
            'state': task.state,
            'result': task.result,
        }
        return HttpResponse(json.dumps(data), content_type='application/json')
    else:
        return HttpResponse('No job id given.')

importnewdata.html:

<!DOCTYPE html>
<html>
<head>
    <title>import new raw data to db</title>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>

</head>
<body style="text-align: center;">

    <h1>select your file to process it!</h1>
    <progress id="progress-bar" value="0" max="100" style="display:none; margin-bottom: 1em;"></progress>

    <form id="process-raw-data" action="/modelmanager/importnewdata/" method="post" enctype="multipart/form-data">
        {% csrf_token %}
        {{  form  }}
        <input type="submit" value="Submit" />
    </form>

{% if task_id %}
    <script type="text/javascript">
        var taskid = "{{task_id}}";
        var frm = $('#process-raw-data');
        var pgrbar = $('#progress-bar');

        get_task_info(taskid);

        function get_task_info(tid) {
            $.ajax({
                type: 'get',
                url: '/modelmanager/get-task-info/',
                data: {'task_id': tid},
                success: function (data) {
                    frm.html('');
                    if (data.state == 'PENDING') {
                        frm.html('Please wait...');
                    }
                    else if (data.state == 'PROGRESS') {
                        pgrbar.css('display', 'inline');
                        pgrbar.val(data.result.percent);
                        frm.html('lines processed ' + data.result.current + ' out of ' + data.result.total);
                    }
                    else if(data.state == 'SUCCESS'){
                        pgrbar.css('display', 'none');
                        frm.html('Successfully Completed!');

                    }
                    if (data.state != 'SUCCESS') {
                        setTimeout(function () {
                            get_task_info(tid)
                        }, 500);
                    }
                },
                error: function (data) {
                    frm.html("error!");
                }
            });
        }
    </script>
{% endif %}


</body>
</html>
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.