Django - 在长时间处理期间显示加载消息

时间:2011-11-29 20:22:40

标签: django django-views loading

如何在django视图中显示请等待加载消息?

我有一个Django视图,需要很长时间才能对大型数据集执行计算。

当进程加载时,我想向用户显示反馈消息,例如:旋转加载动画gif或类似内容。

7 个答案:

答案 0 :(得分:3)

在尝试了布兰登和穆拉特提出的两种不同方法之后,布兰登的建议被证明是最成功的。

  1. 创建一个包含来自http://djangosnippets.org/snippets/679/的javascript的包装器模板。 javascript已被修改:(i)在没有表单的情况下工作(ii)在返回'done'标志时隐藏进度条/显示结果(iii),JSON更新url指向下面描述的视图

  2. 将慢速加载功能移动到线程。该线程将传递一个缓存键,并负责更新缓存的进度状态,然后更新其结果。该线程将原始模板呈现为字符串并将其保存到缓存中。

  3. 创建一个基于upload_progress的视图,从http://djangosnippets.org/snippets/678/修改为(i)代替渲染原始包装模板,如果progress_id =''(ii)生成cache_key,检查缓存是否已存在,如果不存在启动一个新线程(iii)监视线程的进度,完成后将结果传递给包装器模板

  4. 包装器模板通过document.getElementById('main').innerHTML=data.result

  5. 显示结果

    (*查看步骤4是否可以通过重定向更好地实现,因为呈现的模板包含当前未由document.getElementById('main').innerHTML=data.result运行的javascript)

答案 1 :(得分:1)

这是一个老人,但可能会让你朝着正确的方向前进:http://djangosnippets.org/snippets/679/

答案 2 :(得分:1)

更简单的方法是使用您的gif等生成等待页面,然后使用javascript

window.location.href = 'insert results view here';

切换到开始冗长计算的结果视图。在计算完成之前,页面不会更改。完成后,将呈现结果页面。

答案 3 :(得分:1)

您可以做的另一件事是添加一个JavaScript函数,该函数在实际调用Django View之前显示加载图像。

function showLoaderOnClick(url) {
      showLoader();
      window.location=url;
  }
function showLoader(){
      $('body').append('<div style="" id="loadingDiv"><div class="loader">Loading...</div></div>');
  }

然后在您的模板中可以执行以下操作:

<a href='#' onclick="showLoaderOnClick('{% url 'my_namespace:my_view' %}')">This will take some time...</a>

这是一个快速的默认loadingDiv:https://stackoverflow.com/a/41730965/13476073 请注意,这需要jQuery。

答案 4 :(得分:0)

迭代HttpResponse

https://stackoverflow.com/a/1371061/198062

编辑:

我找到了一个用django发送大文件的例子:http://djangosnippets.org/snippets/365/然后我看看FileWrapper类(django.core.servers.basehttp):

class FileWrapper(object):
    """Wrapper to convert file-like objects to iterables"""

    def __init__(self, filelike, blksize=8192):
        self.filelike = filelike
        self.blksize = blksize
        if hasattr(filelike,'close'):
            self.close = filelike.close

    def __getitem__(self,key):
        data = self.filelike.read(self.blksize)
        if data:
            return data
        raise IndexError

    def __iter__(self):
        return self

    def next(self):
        data = self.filelike.read(self.blksize)
        if data:
            return data
        raise StopIteration

我认为我们可以制作一个像这样的可迭代类

class FlushContent(object):
    def __init__(self):
        # some initialization code

    def __getitem__(self,key):
        # send a part of html

    def __iter__(self):
        return self

    def next(self):
        # do some work
        # return some html code
        if finished:
            raise StopIteration

然后在views.py

def long_work(request):
    flushcontent = FlushContent()
    return HttpResponse(flushcontent)

编辑:

示例代码,仍无效:

class FlushContent(object):
    def __init__(self):
        self.stop_index=2
        self.index=0

    def __getitem__(self,key):
        pass

    def __iter__(self):
        return self

    def next(self):
        if self.index==0:
            html="loading"
        elif self.index==1:
            import time
            time.sleep(5)
            html="finished loading"

        self.index+=1

        if self.index>self.stop_index:
            raise StopIteration

        return html

答案 5 :(得分:0)

这是关于如何获取长期加载Django视图的加载消息的另一种解释

进行大量处理的视图(例如,包含多个对象的复杂查询,访问第三方API)可能需要花费一些时间才能加载页面并将其显示在浏览器中。发生的事情是所有这些处理都是在服务器上完成的,而Django无法在完成页面之前为其提供服务。

在处理过程中显示显示加载消息(例如微调gif)的唯一方法是将当前视图分为两个视图:

  1. 第一个视图在不进行任何处理和加载消息的情况下呈现页面

  2. 页面包括对第二个视图的AJAX调用,该视图执行实际处理。使用AJAX / JavaScript完成处理后,处理结果将显示在页面上

答案 6 :(得分:0)

我选择的一种解决方法是使用beforunloadunload事件来显示加载图像。可以与window.load一起使用,也可以不使用。就我而言,视图需要花费大量时间而不是页面加载,因此我没有使用window.load

不利之处在于,即使请求尚未到达服务器或花费大量时间,也会向用户发出错误消息,表明页面正在加载。并且,由于某种原因,请求消失了,用户将继续认为该页面正在加载中。但是我现在正在忍受这个。

P.S。我无法发表评论,因此将其发布为答案。