17.Web

一.WSGL
1.1.WSGL接口的实现
用Python 开发web服务端需要用到WSGL接口,WSGL接口定义很简单,只要求web开发者实现一个函数,就可以响应HTTP请求了。
一个最简单的web项目:

#t17_1.py
def application(environ, start_response):
    start_response('200 OK', [('Content-Type', 'text/html')])
    return b'<h1>sss</h1>'

上面的application函数就是符合WSGL标准的一个HTTP处理函数,我的理解是,这个函数就相当于Java Web中的Servlet的doGet()或doPost()函数,接收的两个参数含义:
environ:一个包含所有HTTP请求信息的dict
start_response:一个发送HTTP响应的函数
函数中调用start_response()就发送了HTTP响应的header,header只能发送一次,所以这个方法也就只能调用一次,接收的两个参数一个是HTTP响应码,另一个是一组list表示的HTTP header,list的每个item是一个包含两个str的tuple,可以理解为key value形式传header。
最后,函数的返回值

b'<h1>sss</h1>'

作为HTTP响应的body发送给客户端。

有了WSGL,我们只需要考虑从environ里拿到HTTP请求信息,然后构造返回信息,通过start_response()发送header,最后返回构造的body。

注意,这个application和doPost()一样,是由服务器来调用的,并不是我们自己调用 的,environ和start_response两个参数我们也不能自己提供,返回的bytes也是由服务器来发送给客户端的,所以我们需要一个WSGL服务器,让这个web应用程序运行起来,测试时可使用Python内置的服务器,需要用到wsgiref模块(用纯Python实现的一个WSGL服务器的参考实现,不考虑性能,仅供开发测试使用)。

1.2运行WSGL服务
上面已经定义了web的处理函数application,现在需要启动WSGL服务器并把这个处理函数设置上,来了请求就由这个函数来处理:

#server.py
from wsgiref.simple_server import make_server

from test17.t17_1 import application

# 创建一个服务器,IP地址为空,端口是8000,处理函数是application:
http = make_server('', 8000, application)
print('Serving HTTP on port 8000')
# 开始监听HTTP请求
http.serve_forever()

再在浏览器访问(因为IP设置的是空,写本机地址):

获取url里的PATH_INFO:

#t17_2.py
def application(environ, start_response):
    start_response('200 OK', [('Content-Type', 'text/html')])
    # 如果端口后面有值就取([1:]是字符串切分,从第1位开始到结尾,目的是去年第一个斜线),否则返回'web',
    body = '<h1>sss , %s' % (environ['PATH_INFO'][1:] or 'web')
    return [body.encode('utf-8')]

二、使用Web框架
1.1使用web框架的意义
上面使用wsgl例子中,通过一个wsgl处理函数来处理所有的请求,根据每个http请求进行响应,注意是用一个处理函数处理所有的请求,我们需要先在接收到请求后在environ里取取出http请求信息判断这个请求是做什么的,再来决定做出什么响应,例如接收到用户登录请求,就得先去判断得知是请求登录的,而不是用户注册的,那么就得去数据库查询看用户是否存在,比对密码是否正确blablabla,如果是用户注册请求,就得去做注册相应的处理,并且有些接口的请求方式还要分POST、GET还是PUT等,不同的请求方式相应的处理也可能会不同,这样一来,所有的接口业务都在这一个地方处理,不说写起来容易出错,后期也无法维护。

1.2使用flask框架

from flask import Flask, request

app = Flask(__name__)


# 主页面
@app.route('/', methods=['GET', 'POST'])
def home():
    return '<h1>Home</h1>'


# 登录页面
@app.route('/signIn', methods=['GET'])
def signIn_page():
    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():
    if request.form['username'] == 'admin' and request.form['password'] == '123':
        return '<h3>Hello admin</h3>'
    return '<h3>Bad username or password</h3>'


if __name__ == '__main__':
    app.run()

===
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)

然后在浏览器访问 http://127.0.0.1:5000/,就会由home()方法接收处理:

请求 http://127.0.0.1:5000/signIn,因为在网页直接输入网址访问是GET请求,就会由signIn_page()方法接收处理:

输入帐号密码后登录,因为form指定以POST方式请求,所以由signIn()方法处理:

如果输入一个错误的帐号或密码,会显示代码中写的错误消息:

有了web框架,就只需要专心处理url对应的处理函数了,上面这几个例子就类似于Java里Spring的映射接口。

三、模板
模板我理解为类似于Java里的jsp,可以嵌入html里配合后台数据更方便生成html;

from flask import Flask, request, render_template

app = Flask(__name__)


# 主页面
@app.route('/', methods=['GET', 'POST'])
def home():
    return render_template('home.html')  # 直接返回home.html页面


# 登录页面
@app.route('/signIn', methods=['GET'])
def signIn_page():
    return render_template('signForm.html')  # 直接返回signForm.html页面


# 登录接口请求
@app.route('/signIn', methods=['POST'])
def signin():
    username_ = request.form['username']
    password_ = request.form['password']
    if username_ == 'admin' and password_ == '123':
        return render_template('sign_ok.html', username=username_)  # 返回sign_ok.html页面并带一个username参数
    return render_template('signForm.html', username=username_,
                           message='Bad Username or password')  # 返回signForm.html页面并带一个username参数和message参数


if __name__ == '__main__':
    app.run()

---
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)

flask用render_template加载网页,默认支持的模板是jinja2:

pip install jinja2

下面是html文件:
home.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1 style="font-style:italic">Home</h1>
</body>
</html>

sign_ok.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>sign ok</title>
</head>
<body>
<p>Welcome, {{ username }}!</p>
</body>
</html>

signForm.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>sign</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>

登录失败的模板复用了signFrom.html文件,通过一行文字来显示错误信息,注意要把模板文件放到templates文件夹下,.py文件和templates文件夹要放到同一级目录下;

操作结果:

猜你喜欢

转载自blog.csdn.net/aislli/article/details/81178544