一、Web框架
有了wsgi,现在我们只需要专注写处理函数相应http请求就行。
但是问题又来了,一个网站肯定不止一个url,如何处理多个不同的url呢?
而且一个url可以对应get和post请求,当然还有其他我们就只考虑这两个,一个简单的想法就是从environ变量取出http请求信息,然后逐个判断
def application(environ, start_response):
method = environ['REQUEST_METHOD']
path = environ['PATH_INFO']
if method=='GET' and PATH=='/'
return handle_home(environ, start_response)
if method=='POST' and path=='/signin'
return handle_signin(environ, start_response)
如果还有很多url,这样写下去没完没了
解决的手段是一个函数来处理一个url,然后怎么知道这个函数是处理哪个url呢?
这交给web框架来做。
我们这里用flask
# C:\Users\ljs>pip install flask
然后写一个app.py,处理3个url,分别是:
- GET /: 首页,返回home
- GET /signin: 登录页,显示登录表单
- POST /signin:处理登录表单,显示登录结果
注意这里同一个url/signin分别有get和post两种请求,映射到两个处理函数中
Flask通过Python的装饰器在内部自动地把URL和函数给关联起来,所以,我们写出来的代码就像这样
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 sigin():
#需要从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()
运行app.py,Flask自带的Server在端口5000上监听
C:\Users\ljs\Desktop>python app.py
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
打开浏览器,输入首页地址http://localhost:5000/

再在浏览器地址栏输入http://localhost:5000/signin,会显示登录表单:

输入用户名admin和口令password,登录成功:

密码输错:

小结
有了Web框架,我们在编写Web应用时,注意力就从WSGI处理函数转移到URL+对应的处理函数,这样,编写Web App就更加简单了。
在编写URL处理函数时,除了配置URL外,从HTTP请求拿到用户数据也是非常重要的。Web框架都提供了自己的API来实现这些功能。Flask通过request.form['name']来获取表单的内容。
二、使用模板
使用了框架后我们发现问题,在让函数返回html字符串?如果html代码很多,还要有css和js,然后全部写在函数里?这也是不现实的。这时候我们就得使用模板了。
1、我们要先准备三个html文档,这不是一个普通的html文档,而是嵌入了一些变量和指令,
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加点判断把form重用成失败的模板就行。
2、然后我们重写app.py,
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()
Flask通过render_template()
函数来实现模板的渲染。和Web框架类似,Python的模板也有很多种。Flask默认支持的模板是jinja2,所以我们先直接安装jinja2:
C:\Users\ljs\Desktop>pip install jinja2
Requirement already satisfied: jinja2 in c:\programdata\anaconda3\lib\site-packages
Requirement already satisfied: MarkupSafe>=0.23 in c:\programdata\anaconda3\lib\site-packages (from jinja2)
You are using pip version 9.0.1, however version 9.0.2 is available.
You should consider upgrading via the 'python -m pip install --upgrade pip' command.
3、最后,把模板放到templates文件夹里,这个文件夹与app.py同目录,然后启动app.py,跟前面是一样的

总结;
上面分离python代码和html代码,这个模式叫做mvc模式
Model-View-Controller,中文名“模型-视图-控制器”。
Python处理URL的函数就是C:Controller,Controller负责业务逻辑,比如检查用户名是否存在,取出用户信息等等;
包含变量{{ name }}的模板就是V:View,View负责显示逻辑,通过简单地替换一些变量,View最终输出的就是用户看到的HTML。
MVC中的Model在哪?Model是用来传给View的,这样View在替换变量的时候,就可以从Model中取出相应的数据。
最后推荐一个送赵雷的画。
网友评论