进度通知
为了完善这个功能,我想在后台任务运行时提醒用户任务完成的百分比进度。 在浏览 Bootstrap 组件选项时,我决定在导航栏的下方使用一个 Alert 组件。 Alert 组件是向用户显示信息的带颜色的横条。 我用蓝色的 Alert 框来渲染闪现的消息。 现在我要添加一个绿色的 Alert 框来显示任务进度。 样式如下:
app/templates/base.html :基础模板中的导出进度 Alert 组件。
...
{% block content %}
<div>
{% if current_user.is_authenticated %}
{% with tasks = current_user.get_tasks_in_progress() %}
{% if tasks %}
{% for task in tasks %}
<div role="alert">
{{ task.description }}
<span id="{{ task.id }}-progress">{{ task.get_progress() }}</span>%
</div>
{% endfor %}
{% endif %}
{% endwith %}
{% endif %}
...
{% endblock %}
...
渲染任务 Alert 组件的方法几乎与闪现消息相同。 外部条件在用户未登录时跳过所有与 Alert 相关的标记。而对于已登录用户,我通过调用前面创建的 get_tasks_in_progress()
方法来获取当前正在进行的任务列表。 在当前版本的应用中,我最多只能得到一个结果,因为我不允许多个导出任务同时执行,但将来我可能要支持可以共存的其他类型的任务,所以以通用的方式渲染 Alert 可以节省我以后的时间。
对于每项任务,我都会在页面上渲染一个 Alert 元素。 Alert 的颜色由第二个 CSS 样式控制,本处是 alert-success
,而在闪现消息是 alert-info
。 Bootstrap 文档 包含有关 Alert 的 HTML 结构的详细信息。 Alert 文本包括存储在 Task
模型中的 description
字段,后面跟着完成百分比。
百分比被封装在具有 id
属性的 <span>
元素中。 原因是我要在收到通知时用 JavaScript 刷新百分比。 我给任务 ID 末尾附加 -progress
来构造 id
属性。 当有通知到达时,通过其中的任务 ID,我可以很容易地使用 #<task.id>-progress
选择器找到正确的 <span>
元素来更新。
如果你此时进行尝试,则每次导航到新页面时都会看到“静态”的进度更新。 你可以注意到,在启动导出任务后,你可以自由导航到应用程序的不同页面,正在运行的任务的状态始终都会展示出来。
为了对 span>
元素的百分比的动态更新做准备,我将在 JavaScript 端编写一个辅助函数:
app/templates/base.html :动态更新任务进度的辅助函数。
...
{% block scripts %}
...
<script>
...
function set_task_progress(task_id, progress) {
$('#' + task_id + '-progress').text(progress);
}
</script>
...
{% endblock %}
这个函数接受一个任务 id
和一个进度值,并使用 jQuery 为这个任务定位 <span>
元素,并将新进度作为其内容写入。 实际上不需要验证页面上是否存在该元素,因为如果没有找到该元素,jQuery 将不会执行任何操作。
app/tasks.py 中的 _set_task_progress()
函数每次更新进度时调用 add_notification()
,就会产生新的通知。 而我在 第二十一章 明智地以完全通用的方式实现了通知功能。 所以当浏览器定期向服务器发送通知更新请求时,浏览器会获得通过 add_notification()
方法添加的任何通知。
但是,这些 JavaScript 代码只能识别具有 unread_message_count
名称的那些通知,并忽略其余部分。 我现在需要做的是扩展该函数,通过调用我上面定义的 set_task_progress()
函数来处理 task_progress
通知。 以下是处理通知更新版本 JavaScript 代码:
app/templates/base.html :通知处理器。
for (var i = 0; i < notifications.length; i++) {
switch (notifications[i].name) {
case 'unread_message_count':
set_message_count(notifications[i].data);
break;
case 'task_progress':
set_task_progress(
notifications[i].data.task_id,
notifications[i].data.progress);
break;
}
since = notifications[i].timestamp;
}
现在我需要处理两个不同的通知,我决定用一个 switch
语句替换检查 unread_message_count
通知名称的 if
语句,该语句包含我现在需要支持的每个通知。 如果你对“C”系列语言不熟悉,就可能从未见过 switch 语句,它提供了一种方便的语法,可以替代一长串的 if/elseif
语句。这是一个很棒的特性,因为当我需要支持更多通知时,只需简单地添加 case
块即可。
回顾一下,RQ 任务附加到 task_progress
通知的数据是一个包含两个元素 task_id
和 progress
的字典,这两个元素是我用来调用 set_task_progress()
的两个参数。
如果你现在运行该应用,则绿色 Alert 框中的进度指示器将每 10 秒刷新一次(因为刷新通知的时间间隔是 10 秒)。
由于本章介绍了新的可翻译字符串,因此需要更新翻译文件。 如果你要维护非英语语言文件,则需要使用 Flask-Babel 刷新翻译文件,然后添加新的翻译:
(venv) $ flask translate update
如果你使用的是西班牙语翻译,那么我已经为你完成了翻译工作,因此可以从 下载包 中提取 app/translations/es/LC_MESSAGES/messages.po 文件,并将其添加到你的项目中。
翻译文件到位后,还要编译翻译文件:
(venv) $ flask translate compile
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论