频道栏目
首页 > 资讯 > HTML/CSS > 正文

flask成长记(二)增强版

17-02-24        来源:[db:作者]  
收藏   我要投稿

flask成长记(二)增强版,要想开发出易于维护的程序,关键在于编写形式简洁且结构良好的代码。到目前为止,你 看到的示例都太简单, 无法说明这一点,但 Flask 视图函数的两个完全独立的作用却被融合在了一起,这就产生了一个问题。

视图函数的作用很明确,即生成请求的响应。

例如,用户在网站中注册了一个新账户。用户在表单中输入电子邮件地址和密码,然后点 

击提交按钮。 服务器接收到包含用户输入数据的请求,然后 Flask 把请求分发到处理注册 

请求的视图函数。 这个视图函数需要访问数据库,添加新用户,然后生成响应回送浏览 

器。这两个过程分别称为业务逻辑和表现逻辑。

把业务逻辑和表现逻辑混在一起会导致代码难以理解和维护。 假设要为一个大型表格构建 

HTML 代码, 表格中的数据由数据库中读取的数据以及必要的 HTML 字符串连接在一起。 

把表现逻辑移到模板中能够提升程序的可维护性。

模板是一个包含响应文本的文件, 其中包含用占位变量表示的动态部分,其具体值只在请 

求的上下文中才能知道。 使用真实值替换变量,再返回最终得到的响应字符串,这一过程 

称为渲染。为了渲染模板, Flask 使用了一个名为 Jinja2 的强大模板引擎。

其实替换就是渲染,还说的那么高大上。

渲染模板

默认情况下, Flask 在程序文件夹中的 templates 子文件夹中寻找模板。在下一个 hello.py 

版本中,要把前面定义的模板保存在 templates 文件夹中,并分别命名为 index.html 和 user. html。

模板渲染的栗子:

from flask import Flask, render_template

# ...

@app.route('/')

def index():

    return render_template('index.html')

@app.route('/user/<name>')

def user(name):

    return render_template('user.html', name=name)

render_template 函数的第一个参数是模板的文件名。 随后的参数都是键值对,

表示模板中变量对应的真实值。在这段代码中,第二个模板收到一个名为 name 的变量。

变量

示例 3-2 在模板中使用的 {{ name }} 结构表示一个变量,它是一种特殊的占位符,告诉模 

板引擎这个位置的值从渲染模板时使用的数据中获取。

<p>A value from a dictionary: {{ mydict['key'] }}.</p>

<p>A value from a list: {{ mylist[3] }}.</p>

<p>A value from a list, with a variable index: {{ mylist[myintvar] }}.</p>

<p>A value from an object's method: {{ myobj.somemethod() }}.</p>

可以使用过滤器修改变量,过滤器名添加在变量名之后,中间使用竖线分隔。例如,下述 

模板以首字母大写形式显示变量 name 的值:

Hello, {{ name|capitalize }}

safe 渲染值时不转义 

capitalize 把值的首字母转换成大写,其他字母转换成小写 

lower 把值转换成小写形式 

upper 把值转换成大写形式 

title 把值中每个单词的首字母都转换成大写 

trim 把值的首尾空格去掉 

striptags 渲染之前把值中所有的 HTML 标签都删掉

完整的过滤器列表可在 Jinja2 文档( http://jinja.pocoo.org/docs/templates/#builtin-filters)中 

查看。

控制结构

Jinja2 提供了多种控制结构,可用来改变模板的渲染流程。本节使用简单的例子介绍其中 

最有用的控制结构。

{% if user %}

    Hello, {{ user }}!

{% else %}

    Hello, Stranger!

{% endif %}

另一种常见需求是在模板中渲染一组元素。下例展示了如何使用 for 循环实现这一需求:

<ul>

    {% for comment in comments %}

        <li>{{ comment }}</li>

    {% endfor %}

</ul>

模板继承

一种重复使用代码的强大方式是模板继承,它类似于 Python 代码中的类继承。首先,创 

建一个名为 base.html 的基模板:

<html>

<head>

    {% block head %}

    <title>{% block title %}{% endblock %} - My Application</title>

    {% endblock %}

</head>

<body>

    {% block body %}

    {% endblock %}

</body>

</html>

block 标签定义的元素可在衍生模板中修改。在本例中,我们定义了名为 head、 title 和 

body 的块。注意, title 包含在 head 中。下面这个示例是基模板的衍生模板:

{% extends "base.html" %}

{% block title %}Index{% endblock %}

{% block head %}

    {{ super() }}

    <style>

    </style>

{% endblock %}

{% block body %}

<h1>Hello, World!</h1>

{% endblock %}

上边的哪一行他是重新弄了一个title 的block吗? 

不不不,只不过是,上边弄了三个block。下面也弄三个block而已。

只是先重写title的block挺难接受的吼。

在 extends 指令之后,基模板中的 3 个块被重新定义,模板引擎会将其插入适当的位置。注意新定义的 head 块,在基模板中其内容不是空的,所以使用 super() 获取原来的内容。

不理解?没关系,反正蜗牛也不理解。

就给了这么简单的栗子,谁的理解能深到哪去,对不对?

使用Flask-Bootstrap集成Twitter Bootstrap

这个是书里面讲的,本来蜗牛做后台用不到这个的,不过遇见了,就学学吧。

反正书也就二百来页,不碍事儿。

Bootstrap( http://getbootstrap.com/)是 Twitter 开发的一个开源框架,它提供的用户界面组 

件可用于创建整洁且具有吸引力的网页,而且这些网页还能兼容所有现代 Web 浏览器。

Bootstrap 是客户端框架, 因此不会直接涉及服务器。服务器需要做的只是提供引用了 

Bootstrap 层 叠 样 式 表( CSS) 和 JavaScript 文 件 的 HTML 响 应, 并 在 HTML、 CSS 和 

JavaScript 代码中实例化所需组件。这些操作最理想的执行场所就是模板。

要想在程序中集成 Bootstrap, 显然要对模板做所有必要的改动。不过,更简单的方法是 

使用一个名为 Flask-Bootstrap 的 Flask 扩展,简化集成的过程。 Flask-Bootstrap 使用 pip 

安装

pip install flask-bootstrap

Flask 扩展一般都在创建程序实例时初始化。

from flask.ext.bootstrap import Bootstrap

# ...

bootstrap = Bootstrap(app)

和Flask-Script 一样, Flask-Bootstrap 也从 flask.ext 命名空间中导入,然后把 

程序实例传入构造方法进行初始化。

初始化 Flask-Bootstrap 之后,就可以在程序中使用一个包含所有 Bootstrap 文件的基模板。 

这个模板利用 Jinja2 的模板继承机制,让程序扩展一个具有基本页面结构的基模板,其中 

就有用来引入 Bootstrap 的元素。下面把 user.html 改写为衍生模板后的新版本。

{% extends "bootstrap/base.html" %}

{% block title %}Flasky{% endblock %}       这个block是重写了title的block

{% block navbar %}                          下面这一大个block是整个的block,导航条的block。

                                            怎么继承的呢?

                                            你知道人家父模板有这个一个东西可以继承,

                                            于是你自己写好,

                                            jinjia2会将你写好的block替换到模板里面。

                                            一般{% block xxxxxxx %}都是重写block了。

<p class="navbar navbar-inverse" role="navigation">

    <p class="container">

        <p class="navbar-header">

            <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">

                <span class="sr-only">Toggle navigation</span>

                <span class="icon-bar"></span>

                <span class="icon-bar"></span>

                <span class="icon-bar"></span>

            </button>

            <a class="navbar-brand" href="/">Flasky</a>

        </p>

        <p class="navbar-collapse collapse">

            <ul class="nav navbar-nav">

                <li><a href="/">Home</a></li>

            </ul>

        </p>

    </p>

</p>

{% endblock %}

                                少说了一点,看见这个{% endblock %}才是真正完成了一个block

{% block content %}             这里又开始了一个新的conent的block。

                                至于里面的内容就看你HTML和css的功底了。

                                蜗牛没学过,蜗牛还得学。

                                蜗牛也很绝望啊。

<p class="container">

    <p class="page-header">

        <h1>Hello, {{ name }}!</h1>

    </p>

</p>

{% endblock %}

怎么个继承法呢?

你首先得知道人家父模板里面有哪些个部分可以重写的吧? 

小技巧:上面那个代码不好看的话,复制到notepad里面,带着颜色看,就一目了然了。

重写其实是以blck为单位的。

重写好了block之后,jinjia2会自动替换(说填充也行)原父模板的响应的地方。

ps:执行上面的程序还得引入一个

pip install flask-script 

这个好像是可以在执行的时候执行命令行还是什么的。

上面这个 user.html 模板定义了 3 个块,分别名为 title、 navbar 和 content。这些块都是 

基模板提供的, 可在衍生模板中重新定义。 title 块的作用很明显,其中的内容会出现在 

渲染后的 HTML 文档头部,放在 < title > 标签中。 navbar 和 content 这两个块分别表示页 

面中的导航条和主体内容。

来来来回回神,刚才不是说,你要填充父模板,要知道人家哪几个block叫你重写吧?

虽然我下了bootstrap( http://getbootstrap.com/)的源码,但是居然没找到父模板在哪里。

算了,找现成的吧:

Flask-Bootstrap 的 base.html 模板还定义了很多其他块,都可在衍生模板中使用。下面列 

出了所有可用的快。

doc                     整个 HTML 文档

html_attribs            <html> 标签的属性

html                    <html> 标签中的内容

head                    <head> 标签中的内容

title                   <title> 标签中的内容

metas                   一组 <meta> 标签

styles                  层叠样式表定义

body_attribs            <body> 标签的属性

body                    <body> 标签中的内容

navbar                  用户定义的导航条

content                 用户定义的页面内容

scripts                 文档底部的 JavaScript 声明

这个不是蜗牛的重点,就不讲了。

自定义错误页面

如果你在浏览器的地址栏中输入了不可用的路由,那么会显示一个状态码为 404 的错误页 

面。现在这个错误页面太简陋、平庸,而且样式和使用了 Bootstrap 的页面不一致。

(其实蜗牛觉得没什么所谓。)

像常规路由一样, Flask 允许程序使用基于模板的自定义错误页面。最常见的错误代码有 

两个: 404, 客户端请求未知页面或路由时显示; 500,有未处理的异常时显示。为这两个 

错误代码指定自定义处理程序的方式如下:

hello.py: 自定义错误页面

@app.errorhandler(404)

def page_not_found(e):

    return render_template('404.html'), 404

@app.errorhandler(500)

def internal_server_error(e):

    return render_template('500.html'), 500

和视图函数一样,错误处理程序也会返回响应。它们还返回与该错误对应的数字状态码。

错误处理程序中引用的模板也需要编写。 这些模板应该和常规页面使用相同的布局,因此 

要有一个导航条和显示错误消息的页面头部。

原教材里面又要讲模板继承了。反正现在用不到,不看了。

链接

任何具有多个路由的程序都需要可以连接不同页面的链接,例如导航条。

在模板中直接编写简单路由的 URL 链接不难,但对于包含可变部分的动态路由,在模板 

中构建正确的 URL 就很困难。而且,直接编写 URL 会对代码中定义的路由产生不必要的 

依赖关系。如果重新定义路由,模板中的链接可能会失效。

为了避免这些问题, Flask 提供了 url_for() 辅助函数,它可以使用程序 URL 映射中保存 

的信息生成 URL。

url_for() 函数最简单的用法是以视图函数名(或者 app.add_url_route() 定义路由时使用 

的端点名)作为参数, 返回对应的 URL。例如,在当前版本的 hello.py 程序中调用 url_ 

for(‘index’) 得到的结果是 /。调用 url_for(‘index’, _external=True) 返回的则是绝对地 

址,在这个示例中是 http://localhost:5000/。

生成连接程序内不同路由的链接时,使用相对地址就足够了。如果要生成在 

浏览器之外使用的链接, 则必须使用绝对地址,例如在电子邮件中发送的 

链接。

使用 url_for() 生成动态地址时,将动态部分作为关键字参数传入。例如, url_for 

(‘user’, name=’john’, _external=True) 的返回结果是 http://localhost:5000/user/john。

静态文件

Web 程序不是仅由 Python 代码和模板组成。大多数程序还会使用静态文件,例如 HTML 

代码中引用的图片、 JavaScript 源码文件和 CSS。

之前那个,不是有个/static路由呢么。那就是存放静态文件的路径。

url_for('static', filename='css/styles.css', _external=True) 得 到 的 结 果 是 http://

localhost:5000/static/css/styles.css。

上面那个就是返回的一个完整的链接。用的是url_for去生成的。

默认设置下, Flask 在程序根目录中名为 static 的子目录中寻找静态文件。如果需要,可在 

static 文件夹中使用子文件夹存放文件。 服务器收到前面那个 URL 后,会生成一个响应, 

包含文件系统中 static/css/styles.css 文件的内容。

下面这个栗子展示了如何在程序的基模板中放置 favicon.ico 图标。这个图标会显示在浏览器的 

地址栏中。

templates/base.html:定义收藏夹图标

{% block head %}

{{ super() }}

<link rel="shortcut icon" href="{{ url_for('static', filename = 'favicon.ico') }}"

    type="image/x-icon">

<link rel="icon" href="{{ url_for('static', filename = 'favicon.ico') }}"

    type="image/x-icon">

{% endblock %}

图标的声明会插入 head 块的末尾。注意如何使用 super() 保留基模板中定义的块的原始 

内容。

相关TAG标签
上一篇:spring集成kafka基于注解kafkaListener
下一篇:Linux文件/文件夹权限小札
相关文章
图文推荐

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站