第5章 Web编程 导学 5.1 学习目标 : ● 了解Web编程基本概念、技术、理论。 ● 理解HTML 语言以及在Web编程中的作用 。 了解常见的Python语言Web框架 。 ● ● 掌握Flask框架的下载、安装和使用。 在计算机应用的历史中,早期程序都是桌面应用程序,只能运行在价格昂贵的大型机 器上。随着个人计算机的逐步普及,应用程序开始安装到普通机器上,而数据库需要运行 在服务器上,这样多个用户就可以共享数据服务,这就是C/S(Client/Server)架构的由来。 自从互联网兴起,越来越多的应用转为基于Web的B/S(Browser/Server)架构程序,主要 原因有以下4点。 (1)B/S架构分布性强,个人计算机上不需要安装客户端,只需要安装浏览器即可,而 浏览器通常由操作系统自带,非常方便。 (2)维护方便,应用程序的升级维护只需要在服务端进行,对客户端不会带来任何影响。 (3)业务扩展简单方便,通过增加网页即可增加服务器功能。 (4)开发简单,共享性强。 所以,到目前为止,除了少数对性能要求较高的大型应用之外,大部分软件都是基于 Web的。Web开发也经历了以下4个阶段。 (1)静态Web页面,通过文本编辑器直接编辑并生成静态的HTML页面,这些页面在 应用使用过程中不会发生变化,如果要修改,需要再次编辑HTML内容。 (2)CGI技术,静态Web页面无法处理用户动态提交的数据,出现了CGI(Common GatewayInterface)技术,使用C/C++实现,这个问题得以解决。 (3)ASP/JSP/PHP技术,由于Web应用修改频繁,用C/C++这样的语言进行Web开 发非常麻烦,不如脚本语言开发效率高。因此市场上出现了基于脚本语言的开发技术,常 见的有ASP 、JSP以及PHP等。 (4)MVC模式,为进一步解决直接用脚本语言嵌入HTML导致的可维护性差的问 题,人们引入了MVC(Model-View-Controler)模式。现在很多Web开发框架都基于MVC 或者类似的模式。 Python是一种解释型的脚本语言,开发效率高,对于Web编程也是一个非常好的选 择。它提供了开发Web应用程序的卓越工具和成熟的编程框架。Python有上百种Web 开发框架和很多成熟的模板技术,选择Python开发Web应用,不但开发效率高,而且运行 速度快。本章首先介绍了Web编程必须掌握的基本概念,供初学者了解基本原理。然后介 绍Flask编程框架,介绍它的模板、表单、cookies、文件上传和部署等。掌握了这些知识之 后,读者就可以开发一些简单的Web应用了。 5.2Web基础 学习Web应用开发,读者首先需要掌握以下概念。 5.1 b 2.We 人们经常提到Web应用开发,但很多初学者搞不清Web到底是什么意思。其实,要清 楚Web到底是什么,涉及其他几个容易混淆的概念。 计算机网络(ComputerNetwork)概念外延最大,它可以是局域网络,也可以是很多计 算机连接而成的互联网。由计算机相互连接而成的大型网络系统都可算是互联网, Internet 是互联网中最大的一个,即因特网。因特网是由许多小的网络互联而成的一个逻辑网,每 个小的网络中还连接着若干台计算机(主机),基于通信协议(例如TCP/IP)和通信子网(例 如网络设备和电缆)实现网络通信。因为因特网是互联网中最大的一个,所以有时也将其 称为互联网。 160 16 1 而Web(world wide web),即全球广域网,也称为万维网,是一种基于超文本 (Hypertext)和HTTP的、全球性的、动态交互的、跨平台的分布式图形信息系统;是建立在 因特网上的一种网络服务,为浏览者在因特网上查找和浏览信息提供了图形化的、易于访 问的直观界面,其中的文档及超链接(Hyperlink)将因特网上的信息结点组织成一个互为关 联的网状结构。Web 页面使用前端编程语言和技术来实现,主要有HTML、CSS 和 JavaScript。Web只是因特网上的一个应用层服务。除了Web外,QQ、E-mail等也是因特 网上其他类型的应用层服务。 在因特网上可以找到许多联网的计算机,通过Web可以使用各种共享资源和应用,例 如下载文件、听音乐、看视频等。所以因特网是Web的交流活动基础,而Web使得因特网 共享信息更为便捷。 5.2.2 HTML HTML(HyperTextMarkupLanguage)的全称为超文本标记语言,预定义了一系列标 签。通过这些标签可以统一文档格式,使分散的因特网资源连接为一个逻辑整体。HTML 文本是由HTML命令组成的描述性文本,可以用于说明文字、图形、动画、声音、表格、链 接等。超 文本是一种组织信息的方式,它通过超链接将文本中的文字、图表与其他信息媒体 相关联。这些相互关联的信息媒体可能在同一文本中,也可能是其他文件,或是地理位置 相距遥远的某台计算机上的文件。这种组织信息方式将分布在不同位置的信息资源用随 机方式进行连接,为人们检索信息提供方便。 HTML是用来标记Web信息如何展示以及其他特性的一种语法规则,最初于1989年 由CERN 的TimBerners-Lee发明。HTML基于早期的语言SGML定义,并简化了其中 的语言元素,这些元素告诉浏览器如何在用户的屏幕上展示数据。HTML历史上有较多版 本,目前流行的版本是HTML5。 下面展示一个简单的HTML页面的示例,如例5-1所示。 【例5-1】 使用HTML示例 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>HTML 示例</title> </head> <body> <h1>这是一个标题。</h1> <p>这是一个段落。</p> <p>这是另一个段落。</p> </body> </html> 上面的例子中,DOCTYPE 用来声明文档标准类型,告诉浏览器这是基于HTML5的 1 62 Web页面,<html>与</html>是一组标签,用来描述文档基于HTML。标签里面可以 嵌入其他标签。这里标签<head>与</head>描述的是网页的相关描述信息,例如网页的 标题等,而<body>与</body>标签之间放的主要是可视化网页内容,这些内容就是要呈 现给网页用户的。其中,标签<h1>与</h1>之间的是一个标题,而<p>与</p>之间 是文章的一个段落。一个普通页面通常是由若干个标题和段落以及其他内容组成。 读者可以使用文本编辑器将例5-1中的代码编辑好,保存为以后缀为.html的文件,然 后使用任意浏览器打开就可以看到页面内容,如图5-1所示。 图5-1 使用浏览器打开HTML页面 HTML中有一个可向服务端提交数据的重要标签———Form (表单)。表单中包含不 同类型的input元素、单选按钮、复选按钮和提交按钮等。下面是一个简单的登录页面,如 例5-2所示。 【例5-2】 登录页面示例 <!DOCTYPE html> <htmllang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="" method="post"> 用户名:<br> <input type="text" name="username" placeholder="输入用户名"> <br> 密码:<br> <input type="password" name="password" placeholder="输入密码"> <br><br> <input type="submit" value="登录"> <input type="reset" value="重置"> </form> 16 3 </body> </html> 上例中有一个表单,表单中的第一个属性action表示服务端的哪个对象来处理用户的 数据,method表示使用哪种HTTP方式提交,常见的是post和get两种方式。表单中有两 个input标签,表示两个输入框。输入框还有多个子类型,使用type属性来区分。输入框 的name属性不能缺少。最后有一个“登录”按钮,单击这个按钮后,用户输入的信息就会提 交到服务端,而单击“重置”按钮,用户输入的信息会被清空。运行效果如图5-2所示。 图5-2 登录页面 5.2.3 URL 5.2.2节中编写的静态HTML网页可以使用浏览器打开,浏览器的上方是一个用来输 入URL的地址栏。通常可以使用该地址栏输入一个网址,来定位一个万维网上面的资源。 所谓URL(UniformResourceLocator)就是统一资源定位器,用来访问存在的资源,由 如下几部分组成。 (1)传送协议,常见的协议有HTTP、FTP、HTTPS等。 (2)层级URL标记符号(为[//],固定不变)。 (3)访问资源需要的凭证信息(可省略)。 (4)服务器(通常为域名,也可以使用IP地址)。 (5)端口号(以数字方式表示,若为HTTP协议,默认端口“:80”可省略)。 (6)路径(以“/”字符区别路径中的每一个目录名称)。 (7)查询(GET模式的窗体参数,以“?”字符为起点,每个参数以“&”隔开,再以“=”分 开参数名称与数据,通常以UTF8的URL编码,避开字符冲突的问题)。 (8)片段,以“#”字符为起点。 以http://www.nuist.edu.cn:80/index.html? page=1#firstSection为例,其中http 是传输的协议,5.2.4节再重点介绍;www.nuist.edu.cn是域名;冒号后面的80是服务器上 的默认网络端口号;后面的/news/index.html是路径;“? page=1”是该请求附带的参数。 最后的#firstSection是该页面上面的某个区域或者片段。这里需要注意的是,大多数网页 浏览器不要求用户输入网页中“htp://”的部分,因为绝大多数网页内容是超文本传输协议 文件。同样,80是HTTP的默认端口号,一般也不必写明。 5.4 HTTP 2. 前面提到的HTTP(HyperTextTransferProtocol)称为超文本传输协议,它是一种用 于分布式、协作式和超媒体信息系统的应用层协议。 HTTP是一个客户端和服务器端请求和应答的标准。通过使用网页浏览器,客户端发 起一个HTTP请求到服务器上某个端口。应答的服务器上存储着一些资源,例如HTML 文件和图像。 HTTP中有若干请求类型,最常用的是两种请求方式:GET与POST请求。简单来 说,这两种方式的区别就是,GET提交的数据会放在URL之后,也就是请求行里面,以“?” 分割URL和传输数据,参数之间以“&”相连,上面的URL示例使用的就是GET请求。而 POST方法是把提交的数据放在HTTP包的请求体中。GET提交的数据大小有限制,而 POST方法提交的数据没有限制。 所有HTTP响应的第一行都是状态行,依次包括当前HTTP版本号,3位数字组成的 状态代码,以及描述状态的短语,彼此之间由空格分隔。状态代码的第一个数字代表当前 响应的类型: (1)1xx表示消息,请求已被服务器接收,继续处理; (2)2xx表示成功,请求已成功被服务器接收、理解、接受; (3)3xx表示重定向,需要后续操作才能完成这一请求; (4)4xx表示请求错误,请求含有词法错误或者无法被执行; (5)5xx表示服务器错误,服务器在处理某个正确请求时发生错误。 最常见的状态码404,表示资源不存在,通常是用户请求的URL错误所致。另一个就 是200,表示请求成功。图5-3展示了浏览器中的请求成功情况,其中的状态码都是200 。 图5-3 状态码 164 16 5 5.3 WSGI 接口 5.3.1 WSGI接口简介 WSGI,全称Web Server GatewayInterface,或者Python Web Server Gateway Interface,是为Python语言定义的Web服务器和Web应用程序或框架之间的一种简单而 通用的接口。 WSGI是一个网关,负责在协议之间进行转换。它作为Web服务器与Web应用程序 或应用框架之间的一种低级别接口,是基于现存的CGI标准而设计的。 很多框架都自带了WSGIserver,例如Flask,web.py,Django、CherryPy等,性能不 高,自带的Webserver主要用于测试。正式发布时多使用生产环境的WSGIserver或者 nginx+uwsgi。 简而言之,WSGI就像是一座桥梁,一边连着Web服务器,另一边连着用户的application 应用。但是,这个桥的功能很弱,有时候还需要别的桥来帮忙才能进行处理。 WSGI有两方:服务器或网关一方,以及应用程序或应用框架一方。服务方调用应用 方,提供环境信息,以及一个回调函数(提供给应用程序用来将消息头传递给服务器方),并 接收Web内容作为返回值。 所谓的WSGI中间件同时实现了API的两方,因此可以在WSGI服务和WSGI应用之 间起调解作用:从WSGI服务器的角度来说,中间件扮演应用程序;而从应用程序的角度来 说,中间件扮演服务器。 “中间件”组件可以执行以下功能: (1)重写环境变量后,根据目标URL,将请求消息路由到不同的应用对象; (2)允许在一个进程中同时运行多个应用程序或应用框架; (3)负载均衡和远程处理,通过在网络上转发请求和响应消息; (4)进行内容后处理。 5.3.2 WSGI接口示例 下面是一个简单的接口示例,如例5-3所示。 【例5-3】 WSGI应用示例 fromwsgiref.simple_server import make_server defrun_server(environ, start_response): start_response('200 OK', [('Content-Type', 'text/html;charset=urf-8')]) return [b'<h1>Hello,world!</h1>',] def start(): httpd =make_server('127.0.0.1', 9900, run_server) # 启动监听服务,端口9900 print('listening 9900.....') 1 66 httpd.serve_forever() if __name__ =='__main__': start() 上例中,start()函数里面定义了一个服务器对象httpd,该服务器基于HTTP,127.0.0.1 表示本机IP地址,9900就是监听端口,run_server是一个处理函数。Serve_forever方法表 示正式启动服务器,此时服务器一直处于被动监听状态。在run_server中有两个参数,其 中environ表示包含所有HTTP请求信息的dict对象,而start_response表示发送HTTP 响应的函数。start_response发送了HTTP响应头部,第一个参数是HTTP状态码,第二 个参数是HTTP头部信息,然后函数返回值作为HTTP响应的Body发送给浏览器。 接下来观察结果如何,首先需要将服务器启动起来(本例中服务端和客户端都在一台 机器上),运行上面的程序,当看到下面的运行结果表示运行成功: listening 9900..... 此时,服务器已经处于监听状态,下面打开浏览器,在地址栏中输入URL,如图5-4 所示。 图5-4 访问首页 如果能看到图5-4中的信息,说明成功了,此时如果查看源代码,就会发现网页的内容 就是从服务端写回的内容,如图5-5所示。 上面的代码只能作为初级演示用,实际上的Web应用远比其复杂,而复杂的Web应用 程序使用WSGI接口处理还是很麻烦的,在WSGI基础之上,一些用来简化Web开发的 Web框架相继出现。 目前主流的PythonWeb框架主要有以下几种。 (1)Flask:热门轻量级Web框架。 (2)Django:全能型Web框架。 图5-5 网页内容 py:一个小巧的Web框架。 (4)Botle:和Flask类似的Web框架。 (5)Tornado:Facebook的开源异步Web框架。 其中,Flask框架相对比较简单,同时也常用于中小型Web系统的开发,下面对其做简 单介绍。 (3)web. 5.4Flask框架 5.4.1 Flask框架简介 Flask是一个用Python编写的Web应用程序框架,由ArminRonacher开发,他领导 一个名为Poco的国际Python爱好者团队。Flask基于WerkzeugWSGI工具包和Jinja2 模板引擎,两者都属于Poco项目。Werkzeug是一个WSGI工具包,它实现了请求、响应 对象和实用函数,可以在其上构建Web框架。Jinja2是Python的一个流行的模板引擎。 Web模板系统将模板与特定数据源组合以呈现动态网页。 Flask通常被称为微框架,它旨在保持应用程序的核心简单且可扩展。默认情况下, Flask不包含数据库抽象层、表单验证,或是其他任何已有的库可以处理的功能。但是, Flask可以通过为应用添加这些功能,如同是Flask原生功能一样。众多的扩展提供了数 据库集成、表单验证、上传处理、各种各样的开放验证等功能。 总体来说,Flask具有如下特点: (1)良好的文档; (2)丰富的插件; (3)包含开发服务器和调试器; (4)支持单元测试; 167 1 68 (5)RESTful请求调度; (6)支持安全cookies; (7)基于Unicode编码。 5.4.2 安装Flask 安装Flask非常简单,进入cmd窗口,然后输入“pip3installflask”就可以开始安装了, 如图5-6所示。 图5-6 安装Flask 5.4.3 简单Flask应用 接下来使用Flask开发一个最简单的Web程序,代码如例5-4所示。 【例5-4】 Flask示例 from flask import Flask app =Flask(__name__) @app.route('/') defhello_world(): return 'Hello World' if __name__ =='__main__': app.run() 这里首先导入了Flask模块,然后使用Flask构造方法创建了一个app对象,该对象实 际上就是WSGI应用程序。“@app.route(/' ')”是一个装饰器,给出了调用的URL。当用户 的前端请求符合该URL规则,就调用hello_world()函数,然后返回该函数的信息到客户端 页面。Hello_world函数也称为视图函数,通常用来处理用户的请求并返回结果。运行该 程序,结果如图5-7所示。 结果可以看出,此时服务端运行起来了,并且在5000端口监听客户端发起的请求。打 开浏览器,在地址栏中输入本地地址localhost:5000,就可以得到结果,如图5-8所示。注 意,端口号5000不可以省略。