第二章 第一个程序,能有多难呐?
整个上一章没写一行代码,现在你需要这个啦,对不?本章,我们将编写第一个程序并逐行解释。同时也包含如何设置开发环境,使用何种工具进行开发,以及如何在程序中使用HTML。
Hello World程序
在学习新编程语言时,我们所写的第一个程序通常都是HelloWorld,通过最小的代码启动一个程序并输出文字"Hello World!"。让我们也用Flask来实现它吧!
预备和工具
首先,确认一下我们正确配置了开发环境。本课程中,我假定你的操作系统是Debian类Linux发行版,如Mint(http://www.linuxmin.com),或者 Ubuntu(http://ubuntu.com)。其中所有的命令操作都将基于这些系统。
接下来,我们先通过apt-get命令安装必需的Debian包:
sudo apt-get install python-dev python-pip
这将安装python开发工具和编译所需要的python库,以及pip:一个灵巧耗用的工具,你可以用它通过命令行来安装自己需要的python包。用起来吧!首先我们安装一个环境管理工具:
sudo pip install virtualenvwrapper
echo "source /usr/local/bin/birtualenvwrapper.sh" >> ~/.bashrc
解释一下上面的操作:sudo
告诉系统我们需要管理员权限来运行后面的命令,pip
是默认的python包管理工具,可以帮我们安装virtualenvwrapper包。第二个命令把命令添加到virtualenvwrapper.sh并加载到当前控制台,以便于在当前shell中运行。
设置虚拟环境
所谓虚拟环境就是python用来隔离不同环境中的开发包的一种方法:它意味着你可以轻松的管理各类包依赖。想象一下,你要定义一个最小的只包含必要的开发包的项目,虚拟环境就可以完美地让你进行测试和输出必需的包。我们将在后面再研究它。现在,按下键盘上的Ctrl+Shift+T
打开一个新的终端,创建我们的helloworld环境,如下:
mkvirtualenv hello
pip install flask
第一行,创建了名为'hello'的虚拟环境,且自动加载环境变量到当前终端。你可以输入deactivate
命令关闭它,也可以通过以下命令来加载激活这一环境:
workon hello #需要的话,用其它的环境名来替换hello
第二行告诉pip去安装Flask包到当前虚拟环境里,在本例中是把flask包安装到hello虚拟环境里。
理解“Hello World”程序
设定完虚拟环境,那我们用啥来编写出漂亮的代码呢?一个编辑器或者是一个IDE(集成开发环境)?如果你的预算低,那么可以尝试一下LightTable editor编辑器(http://lighttable.com)。免费、快速并且易于使用(Ctrl+空格
可以看到所有可用选项),并且它还支持工作空间。这个价格没有更好的了。如果你很幸运有200美刀的预算(或者你拥有自由许可,那就不需要犹豫,直接入手PyCharm IDE吧(https://www.jetbrains.com/pycharm/buy/),它几乎是最好的Python Web开发的IDE了。现在,我们继续。
创建一个文件夹来存放你的项目文件(不是必须的,但如果你这么做了,大家会更喜欢你的),如下:
mkdir hello_world
进入新文件夹后创建文件 main.py:
cd hello_world
touch main.py
main.py文件将包含整个“Hello World”程序代码。其内容应该如下所示:
#coding:utf-8
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello():
return "Hello World!"
if __name__=="__main__":
app.run()
哇塞!就是敲了几个字,对吧?不?哈哈好吧,我明白的。那么,我们刚才都做了什么?
第一行标明我们的main.py文件使用utf-8编码。酷伙计们都这么做,所以别对你的英语非母语的朋友太苛刻。在你的所有python文件中使用它(这样可以在大型项目中帮你预防令人讨厌的低级错误)。
第二行和第三行中,我们导入了Flask类并将其实例化。我们程序的名字是“app”。几乎所有的都跟它(app
)相关联:视图(view
)、蓝图(blueprint
) ,配置(config
)等等。“__name__”
参数是必需的,用来告诉程序从何处查找资源,诸如静态内容或模板等。
为了创建“Hello World”,在用户访问web程序(使用浏览器或别的什么咚咚)的时候,我们需要告诉Flask实例如何应答。因此,Flask拥有叫做路由(route)
的东西。
路由,就是是Flask读取请求头部并决定那个视图(view,译:Flask的视图并不是MVC意义上的视图view,而是类似MVC的控制器Controler
)来应答此请求的方法。它首先分析被请求的URL的路径部分,然后查找是哪个路由被注册到这个路径上。
在HelloWorld例子中,第五行,我们使用路由装饰符来把hello函数注册到根路径("/")。每次当程序接收到路径是“/”的请求时,hello函数就会被调用来应答这个请求。下面的片断展示了如何检查URL中的路径:
from urlparse import urlparse
parsed = urlparse("http://www.google.com/")
assert parsed.path=="/"
你也可以将多个路由映射到同一个函数上,如下:
@app.route('/')
@app.route('/index')
def hello():
return "Hello World"
本例中,“/”和“/index”两个路径都被映射到hello视图函数上。
第六行和第七行,我们完成了应答请求的函数。注意: 它没有参数并且回复友好字符串。它之所以不需要参数是因为请求数据(如被提交的表单form
)可以通过线程安全的变量“request”
来访问,这点我们将在上传章节中进行详细讨论。
关于应答(response),Flask可以多种格式应答请求。在我们的例子中,我们以纯文本应答,但我们还可以JSON或HTML格式应答。
第九行和第十行比较简单,它们检查main.py是以独立脚本还是以模块的形式被调用。如果是脚本,它就会运行内建的开发服务器。让我们试一下:
python main.py
你的终端将会有类似于下面的输出:
Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
在你的浏览器中打开这个地址(http://127.0.0.1:5000/ )就会看到,我们的程序已经正常工作了。
以脚本的形式调用main.py非常简单、便于设置。通常,你只需要安装Flask-Script扩展就可以调用开发服务器。
如果你把main.py作为模块调用,只需要把它用如下代码导入即可:
from main import what_I_want
在测试代码的时候,你可能需要经常这样导入一个app的工厂函数。
这基本上就是我们“Hello World”程序全部需要解释和理解的东西了。目前程序的缺憾就是没有有趣的因素,所以让我们添加上点东西,让程序更有意思些。添加上HTML,CSS,和JavaScript可以更美观些,让我们试试吧。
响应HTML页面
首先,要让我们的hello函数用HTML应答,只需要做如下的更改:
def hello():
return "<html><head><title>Hi there!</title></head>
<body>Hello world!</body></html>",200
在上面的例子中,hello函数返回了HTML格式的字符串以及一个数字。字符串默认情况下被解析为HTML,而200则是表示应答成功的HTTP代码。默认情况下也是返回200。
如果你按F5刷新浏览器,你将注意到页面没有变化。为什么呢?这是因为当源代码变化的时候,Flask开发服务器没有重新载入。只有当你打开程序的调试Debug模式时,才会自动重载。那么让我们修改一下:
app=Flask(__name__)
app.debug=True
现在回到程序运行的终端,按下Ctrl+C组合键来重启服务器(译:windows下,ctrl+c只是停止服务器,需要重新输入命令才能启动。不知道ubuntu下是什么情况
)。你将看到当服务器运行之后,在URL旁边会出现一些新的信息输出——类似于“restarting with stat
”。这说明一旦代码变更,服务器将自动重新加载之。这很棒,但你发现我们刚才犯下了罪行吗:在处理响应的函数中直接定义了输出模板?小心哟,MVC之神正在盯着你(译:MVC模式要求将视图,模型数据,控制器三者分离
)。让我们把视图从控制器中分离开吧。在项目文件夹中创建一个名为templates
的文件夹,并在其中新建index.html
文件。index.html文件内容如下:
<html>
<head><title>Hi there!</title></head>
<body>
Hello world!
</body>
</html>
现在更改你的main.py代码如下:
#coding:utf-8
from flask import Flask,render_template
@app.route("/")
def hello():
return render_template("index.html")
你明白我们做了什么吗?render_template的功能就是从templates/
文件夹(Flask的默认模板文件夹)中加载模板,你可以返回输出来渲染它。
现在让我们添加一些JavaScript和CSS样式。默认情况下,Flask内建的开发服务器会从你的项目文件夹下的static
子文件夹中搜索。我们创建并添加文件到其中,你的项目文件夹层次应该如下所示:
project/
--main.py
--templates/
----index.html
--static/
----js
------jquery.min.js
------foundation.min.js
------modernizr.js
----css
------styles.css
------foundation.min.css
注意,我从foundation.zurb框架(一个很好的css框架你可以从http://foundation.zurb.com/获得)中添加了文件。我建议你也这么做,可以轻松获得一个现代化的,漂亮的站点。你模板中的静态文件路径应该看其来如下:
<script src='/statc/js/modernizr.js'></script>
这个文件夹/static
前面的真实路径默认是Flask在调试模式下调用。如果是实际生产模式下,你就必须使用独立的http服务器来提供静态文件。你可以查看本章最后的附加完整代码。
试着使用更好的CSS样式来改进hello world例子。
总计
设置开发服务器是一个非常重要的任务,我们完成了。创建“Hello World”程序是介绍一项新技术最好的办法,我们也完成了。最后我们学到了如何生成HTML页面并使用静态文件,基本上就是大部分web程序做的。在本章你学到了所有技术,我希望这个过程很轻松并且让你满意。
在下章中,我们添加一点挑战性的调味汁,设置更高级的模板。我们将学习如何使用Jinja2包来创建更棒的模板,并允许我们用最少的输入做的更多。
再会吧!