2022年 11月 8日

python Web开发

目录

本文参考自廖雪峰老师的python教程,旨在理清用python做web开发的思路。

一,HTTP

二,请求一个网页的流程

三,WSGI

四,Web框架

五,模板

六,总结


一,HTTP

http get请求格式:

  1. GET /path HTTP/1.1
  2. Header1: Value1
  3. Header2: Value2
  4. Header3: Value3

http post请求格式:

  1. POST /path HTTP/1.1
  2. Header1: Value1
  3. Header2: Value2
  4. Header3: Value3
  5. body data goes here...

其中另起一行都是\r\n

http 响应格式:

  1. 200 OK
  2. Header1: Value1
  3. Header2: Value2
  4. Header3: Value3
  5. body data goes here...
  • Content-type 指定 Body的数据类型
  • Content-Encoding: gzip 说明Body数据被压缩过

二,请求一个网页的流程

正如之前学习邮件的流程一样,只有对整个流程有宏观的概念,才能更好的把握自己要做什么。来看请求一个网页的流程

  1. 浏览器向服务器发送http请求
  2. 服务器收到请求后,首先解析请求,然后根据请求信息生成html文档
  3. 服务器向浏览器返回一个http响应,并且把生成的html文档作为响应的Body部分
  4. 浏览器解析服务器的http响应,再解析响应Body中的html文档显示在浏览器上

所以如果要做web开发,服务端就要涉及到http请求的接收,解析,http响应的发送。但是这个事儿比较麻烦,耗时。真正的业务只有根据请求生成html。于是我们需要一个接口来做上述复杂耗时的工作。这个接口就是WSGI:Web Server Gateway Interface。

三,WSGI

  1. from wsgiref.simple_server import make_server
  2. def application(environ, start_response): #environ获取请求信息
  3. start_response('200 OK', [('Content-Type', 'text/html')]) #返回响应的Header
  4. return [b'<h1>Hello, web!</h1>'] #返回响应的Body
  5. httpd = make_server('', 8000, application) #python内置的WSGI参考实现服务器,测试用。
  6. httpd.serve_forever() #开始服务
  • 需要一个符合WSGI规范的服务器来调用我们的写的application
  • request信息都可以从environ获取
  • response可以用start_reponse确定头部+return 返回内容组成

启动这个服务器,访问浏览器

  1. 127.0.0.1 - - [27/Dec/2018 16:21:21] "GET / HTTP/1.1" 200 20
  2. 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

  1. from flask import Flask
  2. from flask import request
  3. app = Flask(__name__) #初始化Flask 监听端口在5000上
  4. @app.route('/', methods=['GET', 'POST']) #Flask通过装饰器的模式,绑定url和函数
  5. def home():
  6. return '<h1>Home</h1>'
  7. @app.route('/signin', methods=['GET'])
  8. def signin_form():
  9. return '''<form action="/signin" method="post">
  10. <p>账号:<input name="username"></p>
  11. <p>密码:<input name="password" type="password"></p>
  12. <p><button type="submit">登陆</button></p>
  13. </form>'''
  14. @app.route('/signin', methods=['POST'])
  15. def signin():
  16. #通过request获取请求信息
  17. if request.form['username'] == 'admin' and request.form['password'] == 'password':
  18. return '<h3>Hello, admin!</h3>'
  19. else:
  20. return '<h3>Bad username or password.</h3>'
  21. if __name__ == '__main__':
  22. app.run()

用web框架,比用WSGI方便了很多。可以用一行代码指定 url和函数绑定。获取请求数据使用request来获取。

运行结果:

  1. * Serving Flask app "webflask" (lazy loading)
  2. * Environment: production
  3. WARNING: Do not use the development server in a production environment.
  4. Use a production WSGI server instead.
  5. * Debug mode: off
  6. * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
  7. 127.0.0.1 - - [27/Dec/2018 17:03:28] "GET / HTTP/1.1" 200 -
  8. 127.0.0.1 - - [27/Dec/2018 17:03:43] "GET /signin HTTP/1.1" 200 -
  9. 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 的时候给这个模板提供数据即可。

  1. from flask import Flask
  2. from flask import request
  3. from flask import render_template
  4. app = Flask(__name__)
  5. @app.route('/', methods=['GET', 'POST'])
  6. def home():
  7. return render_template('home.html') #返回home.html模板
  8. @app.route('/signin', methods=['GET'])
  9. def signin_form():
  10. return render_template('form.html')
  11. @app.route('/signin', methods=['POST'])
  12. def signin():
  13. if request.form['username'] == 'admin' and request.form['password'] == 'password':
  14. return render_template('signin-ok.html', username=request.form['username']) #返回signin-ok.html模板 并给模板绑定上数据 {username:xxx}
  15. else:
  16. return render_template('form.html', message='Bad username or password', username=request.form['username']) #返回form.html模板 并给模板绑定上数据 {username:xxx}
  17. if __name__ == '__main__':
  18. app.run()
  1. #home.html
  2. <html>
  3. <head>
  4. <title>Home</title>
  5. </head>
  6. <body>
  7. <h1 style="font-style:italic">Home</h1>
  8. </body>
  9. </html>
  10. #form.html
  11. <html>
  12. <head>
  13. </head>
  14. <body>
  15. {% if message %}
  16. <p style="color:red">{{ message }}</p>
  17. {% endif %}
  18. <form action="/signin" method="post">
  19. <p>账号:<input name="username"></p>
  20. <p>密码:<input name="password" type="password"></p>
  21. <p><button type="submit">登陆</button></p>
  22. </form>
  23. </body>
  24. </html>
  25. #signin-ok.html
  26. <html>
  27. <head>
  28. </head>
  29. <body>
  30. <p>Welcome, {{ username }}!</p>
  31. </body>
  32. </html>

运行结果

六,总结

python的web开发内置了wsgi和一个wsgi服务器参考实现,通过这个wsgi接口理论上可以进行web开发了。但是有三个麻烦的地方。

  1. 必须要自己根据第一个参数判断url。
  2. 自己用第二个参数返回http响应头。
  3. 自己在python代码里写html代码。

为了简化1,2问题,于是有了web框架,如flask ,Django等,他们通过装饰器的方式去绑定url和处理函数。但是任然没有解决第3个问题。

而模板就是为了解决问题3的,templates,如jinja2, Django自带等,采用MVC的思想,单独编写html代码,然后return 的时候绑定数据。

到此,用python做web开发的大致思路就基本通了。特别感谢廖雪峰老师的教程。