【问题标题】:Django - Display loading image while a bash process is runningDjango - 在 bash 进程运行时显示加载图像
【发布时间】:2017-12-16 12:45:02
【问题描述】:

我需要你的帮助,在我看来,我运行了一个 bash 进程,该进程需要时间取决于图像的大小;在处理过程中,我想显示一个加载的 gif 图像和一个句子(例如“请稍候,图像正在处理中”)。我尝试使用模板来做到这一点,但它是在脚本执行结束时呈现的,而不是在它处理时呈现。 有人可以帮我这样做吗?我发现了一个类似的问题“https://stackoverflow.com/questions/8317219/django-show-loading-message-during-long-processing”但答案对我来说不是很清楚,因为我从未使用过ajax。

这是我的看法:

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

将在处理结束时显示的模板:“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>
</div>
        

     {% endblock %}

【问题讨论】:

  • 如果您希望您的 web 应用程序表现得像这样,那么将无法绕过 ajax。所以你应该熟悉这种技术。

标签: python django


【解决方案1】:

您应该查看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)

【讨论】:

    【解决方案2】:

    最好的办法是使用 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在后台进行处理。

    【讨论】:

    • 感谢您的回答,我是否需要将 js 语法添加到您在我的 javascript 块中提到的 ajax 部分,或者只是在 ?
    • 脚本部分之间使用即可。此外,我在该代码中犯了一个错误,我已经纠正了它。 ajax 代码中的dataType 应该是json 而不是ajax
    • 它没有用,我有同样的问题,它处理没有显示任何东西,最后它只显示一个 json 响应:image: "upload.wikimedia.org/wikipedia/commons/b/b1/Loading_icon.gif"
    • 1.该脚本在页面完全呈现之前加载。考虑在&lt;/body&gt; 标记之前添加脚本,并可能使用window.onload 来确保脚本等到所有内容都呈现完毕。这样,您将显示默认的 gif 图像,并且您的 ajax 将在后台运行。如果 ajax 返回并且图像未加载,那是您的实现中的错误。您可能希望在此处显示您添加的一些代码。
    • 你会在这里找到我的views.py和加载“drive.google.com/open?id=0B7K9jTMbrhwIQVBqc2FoWjRVOTQ”的模板,在我的urls.py中我有:url(r'^wmark/',views.getor,name= 'getor'),我照你说的做了
    【解决方案3】:

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

    【讨论】:

    • 你还有你的代码或教程可以帮助我吗?我被困在这上面了。
    • stackoverflow.com/questions/13465711/… 在这篇文章中,您将看到它是如何工作的。 1 - 显示 gif,隐藏其余部分 2- Ajax 调用来处理您的文件 3- 隐藏 gif 并显示其余部分的 ajax 成功函数
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多