Web支持快速入门¶
构建文档数据¶
要在应用程序中使用Web支持包,您需要构建它使用的数据.此数据包括表示文档,搜索索引和节点数据的pickle文件,这些文件用于跟踪文档中注释和其他内容的位置.要做到这一点,你需要创建一个 WebSupport
类的实例并调用它 build()
方法:
from sphinxcontrib.websupport import WebSupport
support = WebSupport(srcdir='/path/to/rst/sources/',
builddir='/path/to/build/outdir',
search='xapian')
support.build()
这将从 srcdir
读取reStructuredText源,并将必要的数据放在 builddir
中. builddir
将包含两个子目录: 一个名为 “data”,其中包含显示文档,搜索文档和向文档添加注释所需的所有数据.另一个目录将被称为“静态”,并包含应该从 “/static” 提供的静态文件.
注解
如果您希望从 “/static” 以外的路径提供静态文件,可以在创建 WebSupport
对象时提供 staticdir 关键字参数。
将Sphinx文档集成到您的Webapp中¶
现在数据已经构建完毕,是时候做一些有用的事了.首先为您的应用程序创建一个 WebSupport
对象:
from sphinxcontrib.websupport import WebSupport
support = WebSupport(datadir='/path/to/the/data',
search='xapian')
对于您将要使用的每组文档,您只需要其中一个.然后,您可以调用它: get_document()
方法来访问单个文档:
contents = support.get_document('contents')
这将返回包含以下项目的字典:
body: 文档的主体为HTML
sidebar: 文档的侧边栏为HTML
relbar: 包含相关文档链接的div
title: 文件的标题
css: 链接到Sphinx使用的CSS文件
script: 包含评论选项的JavaScript
然后可以将此dict用作模板的上下文.目标是轻松与您现有的模板系统集成.使用 Jinja2 的一个例子是:
{%- extends "layout.html" %}
{%- block title %}
{{ document.title }}
{%- endblock %}
{% block css %}
{{ super() }}
{{ document.css|safe }}
<link rel="stylesheet" href="/static/websupport-custom.css" type="text/css">
{% endblock %}
{%- block script %}
{{ super() }}
{{ document.script|safe }}
{%- endblock %}
{%- block relbar %}
{{ document.relbar|safe }}
{%- endblock %}
{%- block body %}
{{ document.body|safe }}
{%- endblock %}
{%- block sidebar %}
{{ document.sidebar|safe }}
{%- endblock %}
认证¶
要使用某些功能(如投票),必须可以对用户进行身份验证.身份验证的详细信息留给您的应用程序.一旦用户通过身份验证,您就可以使用 username 和 moderator 关键字参数将用户的详细信息传递给某些 WebSupport
方法. Web支持包将存储带有注释和投票的用户名.唯一需要注意的是,如果您允许用户更改其用户名,则必须更新websupport包的数据:
support.update_username(old_username, new_username)
username should be a unique string which identifies a user, and moderator
should be a boolean representing whether the user has moderation privileges.
The default value for moderator is False
.
一个示例 Flask 函数检查用户是否登录然后检索文档是:
from sphinxcontrib.websupport.errors import *
@app.route('/<path:docname>')
def doc(docname):
username = g.user.name if g.user else ''
moderator = g.user.moderator if g.user else False
try:
document = support.get_document(docname, username, moderator)
except DocumentNotFoundError:
abort(404)
return render_template('doc.html', document=document)
首先要注意的是 docname 只是请求路径.这样可以从单个视图轻松访问正确的文档.如果用户已通过身份验证,则用户名和审核状态将与docname一起传递到 get_document()
.然后,Web支持包将此数据添加到模板中使用的 COMMENT_OPTIONS
.
注解
这仅适用于从文档根目录提供文档的情况.如果它是从另一个目录提供的,则需要在url路由前加上该目录,并在创建Web支持对象时给出 docroot 关键字参数:
support = WebSupport(..., docroot='docs')
@app.route('/docs/<path:docname>')
执行搜索¶
要使用Sphinx侧边栏内置的搜索表单,请创建一个函数来处理相对于文档根目录的URL ‘search’ 请求.用户的搜索查询将在GET参数中,键为 q.然后使用 get_search_results()
方法检索搜索结果.在 Flask 就像这样:
@app.route('/search')
def search():
q = request.args.get('q')
document = support.get_search_results(q)
return render_template('doc.html', document=document)
请注意,我们使用相同的模板来渲染搜索结果,就像我们渲染文档一样.那是因为 get_search_results()
返回一个上下文字典,其格式与 get_document()
相同.
评论和建议¶
现在已经完成了,现在是时候定义处理来自脚本的AJAX调用的函数了.您将需要三个功能.第一个函数用于添加新注释,并将调用Web支持方法 add_comment()
:
@app.route('/docs/add_comment', methods=['POST'])
def add_comment():
parent_id = request.form.get('parent', '')
node_id = request.form.get('node', '')
text = request.form.get('text', '')
proposal = request.form.get('proposal', '')
username = g.user.name if g.user is not None else 'Anonymous'
comment = support.add_comment(text, node_id='node_id',
parent_id='parent_id',
username=username, proposal=proposal)
return jsonify(comment=comment)
您会注意到 parent_id
和 node_id
都随请求一起发送.如果注释直接附加到节点,则 parent_id
将为空.如果注释是另一个注释的子项,那么 node_id
将为空.然后,下一个函数处理特定节点的注释检索,并且恰当地命名为 get_data()
:
@app.route('/docs/get_comments')
def get_comments():
username = g.user.name if g.user else None
moderator = g.user.moderator if g.user else False
node_id = request.args.get('node', '')
data = support.get_data(node_id, username, moderator)
return jsonify(**data)
需要的最后一个函数将调用 process_vote()
,并将处理用户对评论的投票:
@app.route('/docs/process_vote', methods=['POST'])
def process_vote():
if g.user is None:
abort(401)
comment_id = request.form.get('comment_id')
value = request.form.get('value')
if value is None or comment_id is None:
abort(400)
support.process_vote(comment_id, g.user.id, value)
return "success"
评论审核¶
默认情况下,将自动显示通过 add_comment()
添加的所有注释.如果你想要某种形式的审核,你可以传递 displayed
关键字参数:
comment = support.add_comment(text, node_id='node_id',
parent_id='parent_id',
username=username, proposal=proposal,
displayed=False)
然后,您可以创建一个新视图来处理注释的审核.当主持人决定接受并显示评论时,将调用它:
@app.route('/docs/accept_comment', methods=['POST'])
def accept_comment():
moderator = g.user.moderator if g.user else False
comment_id = request.form.get('id')
support.accept_comment(comment_id, moderator=moderator)
return 'OK'
通过删除评论来拒绝评论.
要在添加新注释但未显示时执行自定义操作(例如通过电子邮件发送主持人),可以在实例化支持对象时将callable传递给 WebSupport
类:
def moderation_callback(comment):
"""Do something..."""
support = WebSupport(..., moderation_callback=moderation_callback)
审核回调必须采用一个参数,该参数将是由:meth:`add_comment`返回的相同注释dict.