天天看点

在Flask框架将其做为后端服务,使用jQuery的AJAX进行交互的实战在Flask里的jQuery使用AJAX

在Flask里的jQuery使用AJAX

JQuery是一个小型JavaScript库,通常用于简化DOM和JavaScript的使用。它是一个非常好的工具,可以通过在服务器和客户端之间交换JSON使网络应用程序更加动态。

JSON是一种非常轻量级的传输格式,非常类似于Python原语(数字、字符串、字典和列表)。JSON受到广泛支持,并且易于解析。几年前,JSON开始流行,并在网络应用程序中迅速取代了XML。

加载jQuery

<script type=text/javascript src="{{
  url_for('static', filename='jquery.js') }}"></script>
           

为了使用jQuery,必须首先下载它,将其放在应用程序的静态目录中,并确保它已加载。理想情况下,你有一个所有页面的布局模板。在模板的<body>底部添加脚本语句以加载jQuery:

使用 Google 的 AJAX 库 API来载入 jQuery:

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="{{
  url_for('static', filename='jquery.js') }}">\x3C/script>')</script>
           

一个简单的方法是向页面添加一个脚本标记,并设置一个全局变量来表示应用程序的根路径。例子:

<script type=text/javascript>
  $SCRIPT_ROOT = {{ request.script_root|tojson|safe }};
</script>
           

在HTML中,script标记用于声明CDATA,也就是说,声明的内容将不会被解析。<the contents between script>and</script>将被视为脚本。这也意味着脚本标记之间没有</。这里|tojson将正确处理问题并转义斜杠({{“</script>”|tojson|safe}}将呈现为“</sscript>”)。

在Flask 0.10中,我们更进一步,用unicode转义了所有HTML标记,以便Flask可以自动将HTML转换为安全标记。

JSON 视图函数

现在,让我们创建一个服务器函数,它接受两个URL参数(两个要添加的数字),并向应用程序返回一个JSON对象。下面的示例非常不切实际,因为类似的工作通常在客户端完成,但它可以简单而清晰地显示如何使用jQuery和Flask:

from flask import Flask, jsonify, render_template, request
app = Flask(__name__)

@app.route('/_add_numbers')
def add_numbers():
    a = request.args.get('a', 0, type=int)
    b = request.args.get('b', 0, type=int)
    return jsonify(result=a + b)

@app.route('/')
def index():
    return render_template('index.html')
           

所见,我还添加了一个索引方法来呈现模板。该模板将如上所述加载jQuery。该模板包含一个用于添加两个数字的表单和一个触发服务器功能的链接。

注意,我们在这里使用get()方法。它不会不打电话。如果字典的键不存在,将返回默认值(此处为0)。此外,它会将值转换为指定的格式(在本例中为int)。在脚本(API、JavaScript等)触发的代码中使用它特别方便,因为在这种情况下不需要特殊的错误报告。

手动推送情境

如果尝试访问请求或在请求上下文之外使用它的任何内容,将收到以下错误消息:

RuntimeError:在请求上下文之外工作。

这通常意味着需要一个活动的HTTP请求来尝试使用该函数。

有关如何避免此问题的信息,请参阅测试文档

这通常仅在测试代码需要活动请求时发生。一种选择是使用测试客户机模拟完整的请求。

或者,可以在

with block_request_Context()

中使用test,块中运行的所有内容都可以访问请求并填写测试数据

def generate_report(year):
    format = request.args.get('format')
    ...

with app.test_request_context(
        '/make_report/2017', data={'format': 'short'}):
    generate_report()
           

拆解回调

拆除回调与请求分派无关,但在出现情况时由情况调用。即使在调度过程中存在未处理的异常和手动推送场景,也会调用这些函数。这意味着不能保证请求调度的任何其他部分会首先运行。确保这些函数的编写方式不依赖于其他回调,并且不会失败。

在测试期间,延迟请求的结束和弹出场景非常有用,以便可以在测试功能中访问其数据。使用withblock_Client()中的test保存情况,直到with块结束。

from flask import Flask, request

app = Flask(__name__)

@app.route('/')
def hello():
    print('during view')
    return 'Hello, World!'

@app.teardown_request
def show_teardown(exception):
    print('after with block')

with app.test_request_context():
    print('during with block')

# teardown functions are called after the context with block exits

with app.test_client() as client:
    client.get('/')
    # the contexts are not popped even though the request ended
    print(request.path)
           

关于代理的说明

Flask提供的一些对象是其他对象的代理。每个工作线程都可以以相同的方式访问代理,但每个工作线程在后台都绑定了一个唯一的对象。

在大多数情况下,你不必关心这个。然而,也有例外。在以下情况下,了解对象是代理对象是有益的:

代理对象不能将其类型伪装为实际的对象类型。如果要执行实例检查,必须检查代理的原始对象。

对象引用非常重要,例如向后台线程发送信号或传递数据。

如果需要访问代理的源对象,请使用_get_ current_ object()方法:

app = current_app._get_current_object()
my_signal.send(app)
           

使用调试器

Flask提供了一个现成的调试器(请参阅调试模式),用于更深入的错误挖掘和跟踪代码执行。如果您需要使用其他Python调试器,请注意调试器之间的干扰。在使用自己的调试器之前,请进行一些参数调整:

  • Debug—是否启用调试模式并捕获异常
  • use_Debugger—是否使用Flask内置调试器
  • use_Reload—模块更改后是否重载和派生进程
  • Debug必须设置为true(即必须捕获异常),另外两个是任意的。

    如果使用Aptana或Eclipse进行故障排除,则use_Debugger和use_Reloaders必须设置为False。一种有用的配置模式如下(当然,缩进应该根据您的应用进行调整):

FLASK:
    DEBUG: True
    DEBUG_WITH_APTANA: True
           
if __name__ == "__main__":
    # To allow aptana to receive errors, set use_debugger=False
    app = create_app(config="config.yaml")

    use_debugger = app.debug and not(app.config.get('DEBUG_WITH_APTANA'))
    app.run(use_debugger=use_debugger, debug=app.debug,
            use_reloader=use_debugger, host='0.0.0.0')
           

注册过滤器

@app.template_filter('reverse')
def reverse_filter(s):
    return s[::-1]

def reverse_filter(s):
    return s[::-1]
app.jinja_env.filters['reverse'] = reverse_filter
           
{% for x in mylist | reverse %}
{% endfor %}