Web支持快速入门

建筑文档数据

要在您的应用程序中使用Web支持包,您需要构建它使用的数据。这些数据包括代表文档的PICLE文件、搜索索引以及用于跟踪注释和其他内容在文档中的位置的节点数据。为此,您需要创建 WebSupport 类,并调用其 build() 方法:

from sphinxcontrib.websupport import WebSupport

support = WebSupport(srcdir='/path/to/rst/sources/',
                     builddir='/path/to/build/outdir',
                     search='xapian')

support.build()

这将阅读reStructuredtext来源 srcdir 并将必要的数据放入 builddir . 的 builddir 将包含两个子目录:一个名为“数据”,包含显示文档、搜索文档以及向文档添加注释所需的所有数据。 另一个目录将被称为“静态”,并包含应从“/静态”提供的静态文件。

备注

如果您希望从“/Static”以外的路径提供静态文件,可以通过提供 staticdir 关键字参数创建 WebSupport 对象。

将Sphinx文档集成到您的Web应用程序中

现在数据已经构建好了,是时候用它做一些有用的事情了。首先,创建一个 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

然后,该词典可以用作模板的上下文。目标是易于与您现有的模板系统集成。使用以下命令的示例 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 %}

身份验证

要使用投票等特定功能,必须能够对用户进行身份验证。身份验证的细节留给您的应用程序。一旦用户通过了身份验证,您就可以将该用户的详细信息传递给某些 WebSupport 方法使用 usernamemoderator 关键字参数。Web支持包将存储带有评论和投票的用户名。唯一需要注意的是,如果您允许用户更改其用户名,则必须更新Web支持包的数据::

support.update_username(old_username, new_username)

username 应该是标识用户的唯一字符串,并且 moderator 应为表示用户是否具有审核权限的布尔值。的缺省值 moderatorFalse

一个例子 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 只是请求路径。这使得从单个视图访问正确的文档变得容易。如果用户已通过身份验证,则用户名和审核状态与文档名一起传递到 get_document() 。然后,Web支持包会将此数据添加到 COMMENT_OPTIONS 模板中使用的。

备注

只有当您的文档是从您的文档根提供时,这才有效。如果它是从另一个目录提供的,则需要在url路由上加上该目录,并提供 docroot 创建Web支持对象时的关键字参数::

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_idnode_id 与请求一起发送。如果评论被直接附加到节点, parent_id 都会是空的。如果该评论是另一个评论的子级,则 node_id 都会是空的。然后,Next函数处理对特定节点的注释的检索,并将其命名为 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)

审核回调必须接受一个参数,该参数将与由返回的注释字典相同 WebSupport.add_comment()