Django - Display loading image while a bash process is running

时间:2017-07-12 07:58:23

标签: python django

I need your help, In my view i run a bash process that takes time depending on the size of the image; while it process i want to display a loading gif image and a sentence (such as "Please wait, the image is being processed"). I tried to did that with a template but it is rendered at the end of execution of the script not while it process. Can someone help me to do that ? I've found a similar question "Django - show loading message during long processing" but the answer wasn't very clear for me because i never used ajax.

This is my view :

def process(request):
    var = Image.objects.order_by('id').last()
    subprocess.call("./step1.sh %s" % (str(var)), shell=True)
    subprocess.call("./step2.sh %s" % (str(var)), shell=True)
    return render(request, 'endexecut.html')

Template that will be displayed at the end of processing: "endexecut.html"

{% extends 'base.html' %}
{% block content %}
<div class="container">
   <div class="row">
     <div class="jumbotron">
         <div class="row">
             <center>
               <p> Your image is processed succesfully ! </p>
             </center>
          </div>
    </div>
</div>

{% endblock %}

3 个答案:

答案 0 :(得分:2)

您应该查看Celery,它可以让您创建作业并对其进行监控。这将取代您的process(request)。使用您自己的process(request),您必须自己实现,如果已经存在解决方案,为什么要这样做。

使用浏览器中的JS(AJAX)可以像这样查询正在运行的子进程的状态:

def task_progress_json(request, job_id):
    """
    A view to report the progress to the user
    :param job_id:
    :param request:
    """
    job = AsyncResult(job_id)
    data = job.result or job.state
    if job.state == states.FAILURE or isinstance(data, Exception):
        data = {'failure': "{}: {}".format(_('Error'), data)}
        if job_id in request.session:
            request.session[job_id] = None
    else:
        # see http://docs.celeryproject.org/en/latest/reference/celery.states.html#std:state-PROPAGATE_STATES
        # and http://docs.celeryproject.org/en/latest/getting-started/next-steps.html#calling-tasks
        if data == states.PENDING:
            last_state = request.session.get(job_id, None)
            if last_state == states.PENDING:
                data = {'failure': "Error: No Job Running"}
                request.session[job_id] = None
            else:
                request.session[job_id] = data
        if isinstance(data, dict):
            next_url = data.pop('next_url', None)
            next_kwargs = data.pop('next_kwargs', {})
            if next_url:
                data['next_url'] = reverse(next_url, kwargs=next_kwargs)
    return HttpResponse(json.dumps(data), content_type='application/json')

在触发流程的视图中,例如当用户点击表单的Submit按钮时,您就会启动该作业:

def form_valid(self, form):
    # this is just an example, implement as you like
    fs = FileSystemStorage(location=settings.IMAGE_ROOT)
    stored_file = fs.save(form.cleaned_data['file'].name, form.cleaned_data['file'])
    job = import_imag_task.delay(stored_file, self.request.user.id, self.spectre.id)
    # this is another view that shows the progress bar
    # the process of the progress bar is displayed according to
    # results fetched from the above task_progress_json request via AJAX
    return HttpResponseRedirect(reverse('import_image_progress') + '?job=' + job.id)

答案 1 :(得分:1)

你最好的拍摄是使用ajax。您只需将视图重写为:

 def process(request):
     return render(request, "endexecut.html")

默认情况下,使用您要使用的任何文本在endexecut模板中显示gif图像。

在模板页面的脚本部分,您可以进行如下的ajax调用:

 $.ajax({
        url: '/some-app/some-view/',
        type: 'GET',
        dataType: 'json',
        success: function(result){
                $('#image-id').attr('src', result.image);
        },
        error: function(xhr){
               alert(xhr.responseText); //Remove this when all is fine.
        }
 });

Ajax指向一个url(你应该在你的url.py中定义),url会指向可以进行长时间bash处理的视图:

  def bash_processing(request):
       # Do your bash processing here
       return JsonResponse({'image': 'image url here'})

这应该对你有用。 但是,如果处理需要很长时间,您可以考虑使用celery在后​​台进行处理。

答案 2 :(得分:0)

我遇到了同样的问题并使用了jquery和ajaxcall。这样,您可以在启动上传时显示gif,并在完成后移除gif。