Web开发
随着互联网的兴起,人们发现CS架构不适合Web,最大的原因是Web应用程序的修改和升级非常迅速,而CS架构需要每个客户端逐个升级桌面APP,因此BS架构开始流行。
在BS架构下,客户端只需浏览器,应用程序的逻辑和数据都存储在服务器端。浏览器只需要请求服务器获取Web页面,并把Web页面展示给用户即可。Web页面也具有极强的交互性。由于Web页面使用HTML编写的,而HTML具备超强的表现力,并且服务端升级后,客户端无需任何部署就可以使用到最新的版本,因此BS架构迅速流行起来。
Web开发的阶段:
1、静态Web页面
2、CGI:Common Gateway Interface
3、ASP/JSP/PHP:脚本语言开发与HTML结合紧密。
4、MVC:Model-View-Controller的模式,ASP发展为ASP.Net,JSP和PHP也有一大堆MVC框架。
Python是一种解释型脚本语言,开发效率高,所以很适合来做WEB开发。Python有上百种Web开发框架,有很多成熟的模板技术。
HTTP协议简介
在Web应用中,服务器把网页传给浏览器,实际上就是把网页的HTML代码发送给浏览器,让浏览器显示出来。而浏览器和服务器之间的传输协议就是HTTP,所以:
HTML是一种用来定义网页的文本,会HTML,就可以编写网页
HTTP是在网络上传输HTML的协议,用于浏览器和服务器的通信。
chrome浏览器视图,开发者,开发者工具,就可以显示开发者工具:
Elements
显示网页的结构,Network
显示浏览器和服务器的通信。我们点Network
,确保第一个小红灯亮着,Chrome就会记录所有浏览器和服务器之间的通信:
当我们在地址栏输入www.sina.com.cn
时,浏览器将显示新浪的首页。在Network
中,定位到第一条记录,点击,右侧将显示Request Headers
,点击右侧的view source
,我们就可以看到浏览器发给新浪服务器的请求了:
最主要的头两行分析如下,第一行为
GET / HTTP/1.1
GET表示一个读取请求,将从服务器获得网页数据,/
表示URL的路径,URL总是以/
开头,/
就表示首页,最后的HTTP/1.1
表示采用的HTTP版本是1.1。目前HTTP协议的版本就是1.1,但是大部分服务器也支持1.0版本,主要区别在于1.1版本允许多个HTTP请求复用一个TCP连接,以加快传输速度。
第二行开始,每一行都类似于Xxx:abcdefg
:
Host: www.sina.com.cn
表示请求的域名是www.sina.com.cn
,如果一天服务器有多个网站,服务器就需要通过Host来区分浏览器请求的是哪个网站。
继续往下找到Response Headers
,点击view source
,显示服务器返回的原始相应数据:
HTTP相应分为Header和Body两部分,我们在Network中看到的Header最重要的几行如下:
200 OK
200
表示一个成功的响应,后面的OK
是说明。失败的响应有404 Not Found
,500Internal Server Error
等。
Content-Type:text/html
Content-Type
指示响应的内容,这里是text/html
表示HTML网页。请注意浏览器就是靠Content-Type
来判断响应的内容是网页还是图片,是时频还是音乐,不是靠URL来判断响应的内容的。
HTTP响应的Body就是HTML源码,我们可以直接查看:
当浏览器读取到新浪首页的HTML源码后,它会解析HTML,显示页面,然后根据HTML里面的各种链接,再发送HTTP请求到新浪服务器,拿到相应的图片、时频、Flash。JavaScript脚本、CSS等各种资源,最终显示出一个完整的页面。我们在Network下回看到很多额外的请求。
HTTP请求
1、浏览器首先向服务器发送HTTP请求,请求包括:
方法:GET–仅请求资源、POST–附带用户数据
路径:由Host头指定–Host:www.sina.com.cn
以及其他相关的Header2、服务器向浏览器返回HTTP相应,相应包括:
响应代码:200表示成功,3xx表示重定向,4xx表示客户端发送的请求有错误,5xx表示服务器端处理时发生了错误;
响应类型:由Content-Type指定;
以及其他相关的Header;
通常服务器的HTTP响应会携带内容,也就是有一个Body,包含响应的内容,网页的HTML源码就在Body中。3、如果浏览器还需要继续向服务器请求其他资源,比如图片,就再次发出HTTP请求,重复步骤1、2。
Web采用的HTTP协议采用了非常简单的请求-响应模式,从而大大简化了开发。当我们编写一个页面时,我们只需要在HTTP请求中把HTML发送出去,不需要考虑如何附带图片、视频等,浏览器如果需要请求图片和视频,它会发送另一个HTTP请求,因此,一个HTTP请求只处理一个资源。
HTTP协议同时具备极强的扩展性,虽然浏览器请求的是http://www.sina.com.cn/的首页,但是新浪在HTML中可以链入其他服务器的资源,比如``=>
,从而将请求压力分散到各个服务器上,并且,一个站点可以链接到其他站点,无数个站点互相链接起来,就形成了World Wide Web,简称WWW。
HTTP格式
每个HTTP请求和相应都遵循相同的格式,一个HTTP包含Header和Body两部分,其中Body是可选的。
HTTP协议是一种文本协议,所以它的格式非常简单。HTTP GET请求的格式:
每个Header一行一个,换行符是\r\n
。HTTP POST请求的格式是:
当遇到连续两个\r\n
时,Header部分结束,后面的数据都是Body。
HTTP相应的格式:
HTTP响应如果包含body,也是通过\r\n\r\n
来分割的。Body数据类型是由Content-Type
来确定的。
HTML简介
HTML定义了一套语法规则,来告诉浏览器如何把一个丰富多彩的页面显示出来。最简单的HTML长这样:
可以用文本编辑器编写HTML,然后保存为hello.html
,双击或者把文件拖到浏览器中,就可以看到效果:
HTML文档就是一些列的Tag组成的,最外层的Tag是<html>
。规范的HTML也包含<head>...</head>
和<body>...<body>
注意不要和HTTP中的Header和Body搞混了。由于HTML是富文档模型,所以还有一系列的Tag来表示链接、图片、表格、表单等等。
CSS简介
CSS是Cascading Style Sheets(层叠样式表),CSS用来控制HTML里的所有元素如何展现,比如,给标题元素<h1>
加一个样式,变成48号字体,灰色,带阴影。
效果如下:
JavaScript简介
JavaScript和Java没有关系。JavaScript是为了让HTML具有交互性而作为脚本语言添加的,JavaScript既可以内嵌到HTML中,也可以从外部链接到HTML中。如果我们希望当用户点击标题时把标题变为红色,就必须通过JavaScript来实现:
如果要学习Web开发,首先要对HTML、CSS和JavaScript作一定的了解。HTML定义了页面的内容,CSS来控制页面元素的样式,而JavaScript负责页面的交互逻辑。
WSGI接口
了解HTTP协议和HTML文档,一个Web应用的本质是:
浏览器发送一个请求—>服务器收到请求,生成一个HTML文档—>服务器把HTML文档作为HTTP相应的Body发送给浏览器—>浏览器收到HTTP响应,从HTTP Body中取出HTML并显示。
最简单的WEB应用就是先把HTML用文件保存好,用一个线程的HTTP服务器软件接收用户请求,从文件中读取HTML,返回。Apache、Nginx、Lighttpd等这些常见的静态服务器就是做这件事情的。
如果要动态生成HTML,就需要把上述步骤自己实现。不过那些工作量很大,所以底层的代码由专门的服务器软件实现,我们用python专注于生成HTML文档。我们不希望接触到TCP连接。HTTP原始请求和响应格式,所以需要一个统一的接口,让我们专心用Python编写Web业务。
这个接口就是WSGI:Web Server Gateway Interface,只要求开发者实现一个函数,就可以相应HTTP请求。最简单的实例如下:
上面的application()
函数就是符合WSGI标准的一个HTTP处理函数,它接收两个参数:
environ:一个包含所有HTTP请求信息的
dict
对象
start_response:一个发送HTTP响应的函数。
在application()
函数中,调用:
start_response(‘200 OK’,[(‘Content-Type’, ‘text/html’)])
就发送了HTTP响应的Header,注意Header只能发送一次,也就是只能调用一次start_response()
函数。start_response()
函数接收两个参数,一个是HTTP响应码,一个是一组list
表示的HTTP Header,每个Header用一个包含两个str
的tuple
表示。
通常情况下,都应该把Connect-Type
头发送给浏览器。其他很多常用的HTTP Header也应该发送。
然后函数的返回值b'<h1>Hello, world!</h1>'
将作为HTTP响应的Body发送给浏览器。
有了WSGI,我们关心的就是如何从environ
这个dict
对象中拿到HTTP请求信息然后构造HTML,通过start_response()
函数发送Header,最后返回Body。
整个application()
函数本身并没有涉及到任何解析HTTP的部分,也就是说,底层代码不需要我们自己编写,我们只负责在更高层次上考虑如何响应请求就可以了。并且application()
必须由WSGI服务器来调用。有很多符合WSGI规范的服务器,我们可以挑选一个来用。Python内置了一个WSGI服务器,这个模块叫wsgiref,它是用纯Python编写的WSGI服务器的参考实现。
运行WSGI服务
我们先编写hello.py,实现WEB应用程序的WSGI处理函数:
然后再编写一个server.py
,负责启动WSGI服务器,加载application()
函数:
两个文件在一个目录下,执行服务器程序:
启动成功后,打开浏览器,输入http://localhost:8000/
就可以看到结果了。
按Ctrl+c
终止服务器。
为了丰富WEB内容,可以在environ
里读取PATH_INFO
,这样可以显示更加动态的内容:
你可以在地址栏输入用户名作为URL的一部分,将返回Hello,xx!
:
无论多么复杂的WEB应用程序,入口都是一个WSGI处理函数。HTTP请求的所有输入信息都可以通过environ
获得,HTTP响应的输出都可以通过start_response()
加上函数返回值作为Body。复杂的Web应用程序,光靠一个WSGI函数来处理还是太底层了,我们需要在WSGI之上再抽象出Web框架,进一步简化开发。
使用Web框架
了解了WSGI框架,我们发现:其实一个WebAPP就是写一个WSGI的处理函数,针对每个HTTP请求进行相应。
但是如何处理HTTP请求不是问题,问题是如何处理100个不同的URL。
每一个URL可以对应GET和POST请求,当然还有PUT、DELETE等请求,但是通常我们只考虑最常见的GET和POST请求。
一个最简单的想法是从environ
变量里取出HTTP请求的信息,然后逐个判断:
这样写下去代码是没法维护的,因为WSGI提供的接口虽然比HTTP接口高级了不少,但是和Web APP的处理逻辑相比,还是比较低级的,我们需要在WSGI接口之上能进一步抽象,让我们专注于用一个函数处理一个URL,至于URL到函数 的映射就交给WEB框架来做。
Python提供了上百个开源的框架,最流行的为flask。
写一个app.py
,处理三个URL,分别是:
1、
GET /
:首页,返回Home
2、GET /signin
:登录页,显示登录表单
3、POST /signin
:处理登录表单,显示登录结果。
同一个URL/signin
分别有GET和POST两种请求,映射到两个处理函数争取。Flask通过Python的装饰器在内部自动地把URL和函数关联起来:
运行python app.py
,Flask自带的Server在端口5000上监听:
在浏览器首页输入:http://localhost:5000/
:
首页显示正确,地址栏输入:http://localhost:5000/signin
:
输入预设的用户名和口令:
实际的Web APP应该拿到用户名和口令后,去数据库查询再对比,来判断用户是否能登录成功。除了Flask,常见的python框架还有:Django、web.py、Bottle、Tornado
有了Web框架,我们在编写Web应用时,注意力就从WSGI处理函数转移到URL+对应的处理函数,编写变得简单。在编写URL处理函数时,除了配置URL外,从HTTP请求拿到用户数据也是非常重要的。Web框架都提供了自己的API来实现这些功能。Flask通过request.form['name']
来获取表单的内容。
使用模板
Web框架把我们从WSGI中拯救出来了,我们只需要不断地编写函数,带上URL,就可以继续Web APP的开发了。Web App最复杂的部分在HTML页面。HTML不仅要正确,还要通过CSS美化,再加上复杂的JavaScript脚本来实现各种交互和动画效果。用python的字符串是无法实现的。所以出现了模板技术。
使用模板首先需要预先准备一个HTML文档,这个HTMl文档不是普通的HTML,而是嵌入了一些变量和指令,然后根据我们传入的数据,替换后得到最终的HTMl,发送给用户:
这就是传说中的MVC:Model-View-Controller,模型-视图-控制器
Python处理URL的函数就是C:Controller,Controller负责业务逻辑,比如检查用户名是否存在,取出用户信息等等。包含变量的模板就是V:View,View负责显示逻辑,通过简单地替换一些变量,View最终输出的就是用户看到的HTML。
上面的例子中,Model就是一个dict
:
{ ‘name’: ‘Michael’}
因为Python支持关键字参数,很多Web框架允许传入关键字参数,然后在框架内部组装出一个dict
作为Model。
对之前的app.py进行改写:
Flask通过render_template()
函数来实现模板的渲染。和Web框架类似,Python的模板也有很多中。Flask默认支持的模板是jinja2,用jinja2来编写模板home.html、显示首页:
form.html:
signin-ok.html: