目录
本文参考自廖雪峰老师的python教程,旨在理清用python做web开发的思路。
一,HTTP
二,请求一个网页的流程
三,WSGI
四,Web框架
五,模板
六,总结
一,HTTP
http get请求格式:
- GET /path HTTP/1.1
- Header1: Value1
- Header2: Value2
- Header3: Value3
http post请求格式:
- POST /path HTTP/1.1
- Header1: Value1
- Header2: Value2
- Header3: Value3
-
- body data goes here...
其中另起一行都是\r\n
http 响应格式:
- 200 OK
- Header1: Value1
- Header2: Value2
- Header3: Value3
-
- body data goes here...
- Content-type 指定 Body的数据类型
- Content-Encoding: gzip 说明Body数据被压缩过
二,请求一个网页的流程
正如之前学习邮件的流程一样,只有对整个流程有宏观的概念,才能更好的把握自己要做什么。来看请求一个网页的流程
- 浏览器向服务器发送http请求
- 服务器收到请求后,首先解析请求,然后根据请求信息生成html文档
- 服务器向浏览器返回一个http响应,并且把生成的html文档作为响应的Body部分
- 浏览器解析服务器的http响应,再解析响应Body中的html文档显示在浏览器上
所以如果要做web开发,服务端就要涉及到http请求的接收,解析,http响应的发送。但是这个事儿比较麻烦,耗时。真正的业务只有根据请求生成html。于是我们需要一个接口来做上述复杂耗时的工作。这个接口就是WSGI:Web Server Gateway Interface。
三,WSGI
- from wsgiref.simple_server import make_server
-
- def application(environ, start_response): #environ获取请求信息
- start_response('200 OK', [('Content-Type', 'text/html')]) #返回响应的Header
- return [b'<h1>Hello, web!</h1>'] #返回响应的Body
-
- httpd = make_server('', 8000, application) #python内置的WSGI参考实现服务器,测试用。
- httpd.serve_forever() #开始服务
- 需要一个符合WSGI规范的服务器来调用我们的写的application
- request信息都可以从environ获取
- response可以用start_reponse确定头部+return 返回内容组成
启动这个服务器,访问浏览器
- 127.0.0.1 - - [27/Dec/2018 16:21:21] "GET / HTTP/1.1" 200 20
- 127.0.0.1 - - [27/Dec/2018 16:21:21] "GET /favicon.ico HTTP/1.1" 200 20
四,Web框架
理论上,用上面的WSGI就完全足够开发web应用了。但是开发效率比较低,所以就有了各种各样的web框架来提高开发效率。
以Flask为例 首先安装flask模块 pip install flask
- from flask import Flask
- from flask import request
-
- app = Flask(__name__) #初始化Flask 监听端口在5000上
-
- @app.route('/', methods=['GET', 'POST']) #Flask通过装饰器的模式,绑定url和函数
- 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">登陆</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>'
- else:
- return '<h3>Bad username or password.</h3>'
-
- if __name__ == '__main__':
- app.run()
用web框架,比用WSGI方便了很多。可以用一行代码指定 url和函数绑定。获取请求数据使用request来获取。
运行结果:
- * Serving Flask app "webflask" (lazy loading)
- * Environment: production
- WARNING: Do not use the development server in a production environment.
- Use a production WSGI server instead.
- * Debug mode: off
- * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
- 127.0.0.1 - - [27/Dec/2018 17:03:28] "GET / HTTP/1.1" 200 -
- 127.0.0.1 - - [27/Dec/2018 17:03:43] "GET /signin HTTP/1.1" 200 -
- 127.0.0.1 - - [27/Dec/2018 17:04:09] "POST /signin HTTP/1.1" 200 -
五,模板
web框架解决了wsgi绑定判断url的麻烦,但是return 的http响应内容依然是字符串拼接,也就是需要在python代码里面用字符串写html代码。这就很难受了。当然,我们可以自己用编辑器写好html代码,然后读取这个html文件也是可以的。不过这是个比较麻烦的事儿。所以就有了模板templates。用MVC的思想,直接用写好html模板,然后return 的时候给这个模板提供数据即可。
- from flask import Flask
- from flask import request
- from flask import 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_form():
- return render_template('form.html')
-
- @app.route('/signin', methods=['POST'])
- def signin():
- if request.form['username'] == 'admin' and request.form['password'] == 'password':
- return render_template('signin-ok.html', username=request.form['username']) #返回signin-ok.html模板 并给模板绑定上数据 {username:xxx}
- else:
- return render_template('form.html', message='Bad username or password', username=request.form['username']) #返回form.html模板 并给模板绑定上数据 {username:xxx}
-
- if __name__ == '__main__':
- app.run()
- #home.html
- <html>
- <head>
- <title>Home</title>
- </head>
- <body>
- <h1 style="font-style:italic">Home</h1>
- </body>
- </html>
-
- #form.html
- <html>
- <head>
- </head>
- <body>
- {% if message %}
- <p style="color:red">{{ message }}</p>
- {% endif %}
-
- <form action="/signin" method="post">
- <p>账号:<input name="username"></p>
- <p>密码:<input name="password" type="password"></p>
- <p><button type="submit">登陆</button></p>
- </form>
- </body>
- </html>
-
- #signin-ok.html
- <html>
- <head>
- </head>
- <body>
- <p>Welcome, {{ username }}!</p>
- </body>
- </html>
运行结果
六,总结
python的web开发内置了wsgi和一个wsgi服务器参考实现,通过这个wsgi接口理论上可以进行web开发了。但是有三个麻烦的地方。
- 必须要自己根据第一个参数判断url。
- 自己用第二个参数返回http响应头。
- 自己在python代码里写html代码。
为了简化1,2问题,于是有了web框架,如flask ,Django等,他们通过装饰器的方式去绑定url和处理函数。但是任然没有解决第3个问题。
而模板就是为了解决问题3的,templates,如jinja2, Django自带等,采用MVC的思想,单独编写html代码,然后return 的时候绑定数据。
到此,用python做web开发的大致思路就基本通了。特别感谢廖雪峰老师的教程。