【问题标题】:Output log file through Ajax in Django在 Django 中通过 Ajax 输出日志文件
【发布时间】:2013-05-04 14:51:09
【问题描述】:

我遵循了一个 SO 接受的关于如何从 here 的 /var/log/gateway 读取 Django 中的日志文件的答案,并且我设法在终端上输出文件,就像这里一样。

2013-05-09T11:15:02.539091+08:00 localhost gateway[5205]: System starting up...
2013-05-09T12:57:44.160246+08:00 localhost gateway[5205]: System start complete.
2013-05-09T15:13:47.428553+08:00 localhost gateway[4777]: * Unable to connect to device /home/smartsensor1. Device may be offline. *

下一步是,我想输出日志文件并以 html 显示,我是这样对原始代码稍作修改的。

def Logs(request):
    with open('../../../../../var/log/gateway') as f:
        while True:
            line = f.readline()
            if line:
                print line
                return HttpResponse(line)

所以在客户端,我根据另一个 SO 接受的答案 here 将 Ajax 放在这样的位置。

$.ajax({
    type: "GET", 
    url : "{% url WebServiceApp.logging.Logs %}",
    success: function (data) {
            $("#output").append(data);
            setTimeout("doUpdate()", 2000);
    }
});
}

setTimeout("doUpdate()", 2000);

这样,来自 Ajax 的输出数据继续显示在日志文件的第一行。在这种情况下,是这样的

2013-05-09T11:15:02.539091+08:00 localhost gateway[5205]: System starting up...
2013-05-09T11:15:02.539091+08:00 localhost gateway[5205]: System starting up...
2013-05-09T11:15:02.539091+08:00 localhost gateway[5205]: System starting up...

我知道会发生这种情况,因为每次 ajax 访问服务器时,服务器都会执行它需要做的事情并将输出发送回日志文件的第一行并通过 HttpResponse 输出并完成循环,但它从未得到有机会做另一条线,因为它已经完成了。当另一个查询完成时,它会一次又一次地做同样的事情。

所以可能的解决方案是客户端询问服务器一次,服务器保持逐行输出日志文件并将其发送给客户端。我不确定这是否可能,所以在这里我问任何专家如何可能实现我可以逐行输出日志文件的结果/

【问题讨论】:

  • 保持连接打开并在生成时发送附加数据称为长轮询 - 但我不确定您将如何在 django 中实现这一点。顺便说一句,考虑使用绝对而不是相对 URL - 当您的应用安装在子目录中时会发生什么?
  • 你可以使用 websockets 建立持久连接
  • 哦,好的。让我阅读有关日志轮询的信息,也许它会给我提示如何在这里解决我的问题。嗯,感谢您对 url 的评论,但是当我使用绝对 url 而不是相对 url 时会不会导致同样的问题?我的意思是它仍然找不到它?
  • @dm03514 谢谢。我忘了在我的问题中提到应用任何并行服务器目前不是一个选项。所以我不得不使用ajax或者暂时看一下Basic提到的这个long polling。
  • re: urls /var/log/blah 总是指向同一个地方。 ../../../var/log/blah 将改变它指向的位置,这取决于从哪里请求路径。例如,从/srv/www/test 指向/var/log/blah,但从/srv/www/test/something 指向/srv/var/log/blah

标签: jquery python ajax django


【解决方案1】:

好吧,你可以使用这样的想法:

使用GET 参数,您可以像这样控制视图的方法:

def Logs(request):
    whole_file = True
    if request.GET.get('whole_file') == 0:
        whole_file = False
    return_string = ''
    with open('../../../../../var/log/gateway') as f:
        while True:
            line = f.readline()
            if line:
                return_string += line + '<br>' # <br> is for breakline html, do it your way
                if not whole_file: break # break if you only need first line
    return HttpResponse(line)

这样,您在 get 参数中包含一个变量,告诉您的视图是返回整个日志文件(第一次)还是只返回第一行(下一次)。

然后在您的 ajax 中,您必须包含一种将 GET 参数插入 url 的方法。您使用 {{url}} 标记,我不太确定如何使用它,但我相信您会在文档中找到一些东西,如果您不能尝试其他方法,例如静态字符串(不是非常漂亮)或为它创建自己的自定义标签。

这将是您可能使用的 javascript 的示例:

$.ajax({
    type: "GET", 
    url : "/ajax_log/?whole_file=0", //this will request the whole file
    success: function (data) {
            $("#output").append(data);
            setTimeout("doUpdate()", 2000);
    }
});
}

setTimeout("doNextUpdate()", 2000);

function doNextUpdate(){

    $.ajax({
        type: "GET", 
        url : "/ajax_log/?whole_file=1", //this will request the just the first line            success: function (data) {
                $("#output").append(data);
                setTimeout("doUpdate()", 2000);
        }
    });
    }
}

这是我完成你想要的事情的想法。希望对你有帮助。

【讨论】:

    【解决方案2】:

    我找到了解决此问题的方法是执行服务器发送事件

    在服务器端,我使用依赖于ssedjango-sse

    import os
    from django.conf import settings
    from django.views.generic import View
    from django_sse.views import BaseSseView
    import time
    from django.utils.timezone import now
    from datetime import datetime
    from django.utils.timezone import now
    from dateutil import parser
    
    class MySseEvents(BaseSseView):
        def iterator(self):
            while True:
                if not os.path.exists('/var/log/gateway'):
                    file('/var/log/gateway', 'w+').close()
                with open('/var/log/gateway') as f:
                    while True:
                        #get the current time
                        currenttime = now()
                        #read a line from gateway
                        line = f.readline()
                        if line:
                            #split the line read into 4 section
                            str = line.split(' ',3)
                            #compare if the time from the log file is less than the current time
                            logtime = parser.parse(str[0])
                            if logtime >= currenttime:
                                #print when the log is written after the current time
                                output = '%s: %s' % (datetime.strftime(logtime,'%d/%m %H:%M %p'), str[3])
                                self.sse.add_message("line", output)
                                time.sleep(1)
                                yield
    

    我在上面所做的if logtime &gt;= currenttime: 检查是为了确保 html 仅在页面加载后打印出日志,而不是整个日志文件。

    然后在 HTML5 方面,我做了类似于作者在我提供的第一个链接上显示的示例。

    <div id="tab9" class="tab_content">
        <table>
            <tr>
                <td>
                    <p> Shows the records of the logs on gateway.</p>
                    <div style="border:1px solid; height: 200px; width: 850px; overflow: auto;" id="output"></div>
                </td>
            </tr>
        </table>
    </div>
    <script>
    $(document).ready(function() {
        var source = new EventSource('/gtwy/logging/');
        var events_dom = $("#output");
    
        source.addEventListener("line", function(e) {
            events_dom.append(e.data + "<br>");
        });
    });
    </script>
    

    使用它,我设法显示可用的日志。我面临的唯一问题是创建需要权限的网关文件本身,因为我试图在/var/log 中创建它。

    【讨论】:

      猜你喜欢
      • 2016-02-21
      • 2012-04-21
      • 2017-04-09
      • 2015-11-21
      • 2016-05-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多