Web支持快速入门

生成文档数据

要在应用程序中使用Web支持包,您需要生成它使用的数据。此数据包括表示文档、搜索索引和节点数据的pickle文件,这些文件用于跟踪文档中注释和其他内容的位置。您需要创建一个 WebSupport 类的实例并调用它的:meth:~.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” 以外的路径提供静态文件,可以在创建:class:~.WebSupport 对象时提供*staticdir* 关键字参数。

将Sphinx文档集成到您的Webapp中

现在数据已经生成完毕,是时候做一些有用的事了。首先为您的应用程序创建一个:class:~.WebSupport 对象:

from sphinxcontrib.websupport import WebSupport

support = WebSupport(datadir='/path/to/the/data',
                     search='xapian')

对于您将要使用的每组文档,您只需要其中一个。然后,您可以调用它的:meth:~.WebSupport.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 %}

认证

要使用某些功能(如投票),必须可以对用户进行身份验证。身份验证的详细信息留给您的应用程序处理。一旦用户通过身份验证,您就可以使用 *用户名*和 *管理员*关键字参数,将用户的详细信息传递给特定 :class:`~.WebSupport`方法。 Web支持包将存储带有注释和投票的用户名。唯一需要注意的是,如果您允许用户更改其用户名,则必须更新websupport包的数据:

support.update_username(old_username, new_username)

*用户名*应该是标识用户的唯一字符串,而*审核人*应该是布尔值,表示用户是否具有审核权限。*审核人*的默认值为“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)

首先要注意的是 *文件名*只是请求路径。这样可以从单个视图轻松访问正确的文档。如果用户已通过身份验证,则用户名和审核状态将与文件名一起传递到:meth:~.WebSupport.get_document。然后,Web支持包将此数据添加到模板中使用的 “COMMENT_OPTIONS”。

备注

This only works if your documentation is served from your document root. If it is served from another directory, you will need to prefix the url route with that directory, and give the docroot keyword argument when creating the web support object:

support = WebSupport(..., docroot='docs')

@app.route('/docs/<path:docname>')

执行搜索

To use the search form built-in to the Sphinx sidebar, create a function to handle requests to the URL ‘search’ relative to the documentation root. The user’s search query will be in the GET parameters, with the key q. Then use the get_search_results() method to retrieve search results. In Flask that would be like this:

@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() 返回一个上下文字典,其格式与:meth:~.WebSupport.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 ”将为空。然后,下一个函数处理特定节点的注释检索,并且恰当地命名为:meth:~sphinxcontrib.websupport.WebSupport.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)

需要的最后一个函数将调用:meth:~.WebSupport.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"

注释审核

默认情况下,将自动显示通过:meth:~.WebSupport.add_comment 添加的所有注释。如果你想要某种形式的审核,你可以传递 “显示”关键字参数:

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传递给:class:~.WebSupport 类:

def moderation_callback(comment):
    """Do something..."""

support = WebSupport(..., moderation_callback=moderation_callback)

The moderation callback must take one argument, which will be the same comment dict that is returned by WebSupport.add_comment().