web应用的本质
1、浏览器发送一个HTTP请求;
2、服务器收到请求,生成一个HTML文档;
3、服务器把HTML文档作为HTTP响应的Body发送给浏览器;
4、浏览器收到HTTP响应,从HTTP Body取出HTML文档并显示。
WSGI:Web Server Gateway Interface。
WSGI接口定义非常简单,它只要求Web开发者实现一个函数,就可以响应HTTP请求
实现Web应用程序的WSGI处理函数,如下
HTTP请求的所有输入信息都可以通过environ获得,HTTP响应的输出都可以通过start_response()加上函数返回值作为Body。
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
def application(environ, start_response):
# Header只能发送一次,也就是只能调用一次start_response()函数
start_response('200 OK', [('Content-Type', 'text/html')])
body = '<h1>Hello, %s!</h1>' % (environ['PATH_INFO'][1:] or 'web')
return [body.encode('utf-8')]
environ:一个包含所有HTTP请求信息的dict对象;
start_response:一个发送HTTP响应的函数。
Python内置了一个WSGI服务器,这个模块叫wsgiref,它是用纯Python编写的WSGI服务器的参考实现。所谓“参考实现”是指该实现完全符合WSGI标准,但是不考虑任何运行效率,仅供开发和测试使用。
无论多么复杂的Web应用程序,入口都是一个WSGI处理函数。
负责启动WSGI服务器,加载application()函数:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# 从wsgiref模块导入:
from wsgiref.simple_server import make_server
# 导入我们自己编写的application函数:
from hello2 import application
# 创建一个服务器,IP地址为空,端口是8000,处理函数是application:
# 如果8000端口已被其他程序占用,启动将失败,请修改成其他端口
httpd = make_server('', 8000, application)
print('Serving HTTP on port 8000...')
# 开始监听HTTP请求:
httpd.serve_forever()
启动成功后,打开浏览器,输入http://localhost:8000/
确保以上两个文件在同一个目录下,然后在命令行启动WSGI服务
使用Web框架Flask
用Flask编写Web App比WSGI接口简单
然后写一个app.py,处理3个URL,分别是:
GET /:首页,返回Home;
GET /signin:登录页,显示登录表单;
POST /signin:处理登录表单,显示登录结果。
注意噢,同一个URL/signin分别有GET和POST两种请求,映射到两个处理函数中。
Flask通过Python的装饰器在内部自动地把URL和函数给关联起来
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from flask import Flask
from flask import request
app = Flask(__name__)
@app.route('/', methods=['GET', 'POST'])
def home():
return '<h1>Home</h1>'
@app.route('/signin', methods=['GET'])
def signin_form():
return '''<form action="/signin" method="post">
<p><input name="username"></p>
<p><input name="password" type="password"></p>
<p><button type="submit">Sign In</button></p>
</form>'''
@app.route('/signin', methods=['POST'])
def signin():
# 需要从request对象读取表单内容:
if request.form['username']=='admin' and request.form['password']=='password':
return '<h3>Hello, admin!</h3>'
return '<h3>Bad username or password.</h3>'
if __name__ == '__main__':
app.run()
直接运行,Flask自带的Server在端口5000上监听
打开浏览器输入http://localhost:5000/
输入http://localhost:5000/signin
输入admin和password登录成功,否则登录失败
除了Flask,常见的Python Web框架还有:
使用模板
Flask通过render_template()函数来实现模板的渲染
和Web框架类似,Python的模板也有很多种。Flask默认支持的模板是jinja2
有了MVC,我们就分离了Python代码和HTML代码。HTML代码全部放到模板里,写起来更有效率
继续用上面的例子用MVC模式改写
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from flask import Flask, request, render_template
app = Flask(__name__)
@app.route('/', methods=['GET', 'POST'])
def home():
return render_template('home.html')
@app.route('/signin', methods=['GET'])
def signin_form():
return render_template('form.html')
@app.route('/signin', methods=['POST'])
def signin():
username = request.form['username']
password = request.form['password']
if username=='admin' and password=='password':
return render_template('signin-ok.html', username=username)
return render_template('form.html', message='Bad username or password', username=username)
if __name__ == '__main__':
app.run()
编写jinja2模板
home.html
<html>
<head>
<title>Home</title>
</head>
<body>
<h1 style="font-style:italic">Home</h1>
</body>
</html>
form.html 用来显示登录表单的模板
<html>
<head>
<title>Please Sign In</title>
</head>
<body>
{% if message %}
<p style="color:red">{{ message }}</p>
{% endif %}
<form action="/signin" method="post">
<legend>Please sign in:</legend>
<p><input name="username" placeholder="Username" value="{{ username }}"></p>
<p><input name="password" placeholder="Password" type="password"></p>
<p><button type="submit">Sign In</button></p>
</form>
</body>
</html>
signin-ok.html 登录成功的模板
<html>
<head>
<title>Welcome, {{ username }}</title>
</head>
<body>
<p>Welcome, {{ username }}!</p>
</body>
</html>
登录失败的模板在form.html中加了一条判断,把form.html重用为登录失败的模板
把模板放到正确的templates
目录下,templates
和app.py
在同级目录下
启动python app.py
在Jinja2模板中,我们用{{ name }}表示一个需要替换的变量。很多时候,还需要循环、条件判断等指令语句,在Jinja2中,用{% ... %}表示指令。
比如循环输出页码:
{% for i in page_list %}
<a href="/page/{{ i }}">{{ i }}</a>
{% endfor %}
如果page_list
是一个list:[1, 2, 3, 4, 5]
,上面的模板将输出5个超链接。
除了Jinja2
,常见的模板还有: