web框架
Web框架(Web framework)是一种开发框架,用来支持动态网站、网络应用和网络服务的开发。这大多数的web框架提供了一套开发和部署网站的方式,也为web行为提供了一套通用的方法。web框架已经实现了很多功能,开发人员使用框架提供的方法并且完成自己的业务逻辑,就能快速开发web应用了。浏览器和服务器的是基于HTTP协议进行通信的。也可以说web框架就是在以上十几行代码基础张扩展出来的,有很多简单方便使用的方法,大大提高了开发的效率。
wsgiref模块
最简单的Web应用就是先把HTML用文件保存好,用一个现成的HTTP服务器软件,接收用户请求,从文件中读取HTML,返回。
如果要动态生成HTML,就需要把上述步骤自己来实现。不过,接受HTTP请求、解析HTTP请求、发送HTTP响应都是苦力活,如果我们自己来写这些底层代码,还没开始写动态HTML呢,就得花个把月去读HTTP规范。
正确的做法是底层代码由专门的服务器软件实现,我们用Python专注于生成HTML文档。因为我们不希望接触到TCP连接、HTTP原始请求和响应格式,所以,需要一个统一的接口协议来实现这样的服务器软件,让我们专心用Python编写Web业务。这个接口就是WSGI:Web Server Gateway Interface。而wsgiref模块就是python基于wsgi协议开发的服务模块。
from wsgiref.simple_server import make_server def application(environ, start_response): # 按着http协议解析数据:environ---请求 # 按着http协议组装数据:start_response---响应 # print(environ) # print(type(environ)) # <class 'dict'> start_response("200 OK", [("Content-type", "text/html")]) # 这个格式是固定的,必须是这样(响应状态码, [(响应头), (响应头)...]) # 得到请求路径 path = environ.get("PATH_INFO") # 对请求路径进行判断 if path == "/login": return [b"<h1>login</h1>"] # 返回必须是列表类型 elif path == "/index": return [b"<h1>index</h1>"] # 返回必须是列表类型 else: return [b"<h1>hello world</h1>"] # 返回必须是列表类型 # 封装socket httped = make_server("", 8090, application) # 等待用户连接:conn, addr = sock.accept() httped.serve_forever() # 会调用application(environ, start_response)
DIY一个web框架
models.py
# 在数据库生成用户表,在项目执行前只需运行一次即可,把所有创建数据表的操作都放在此文件即可 import pymysql conn = pymysql.connect( host="127.0.0.1", port=3306, user="root", password="123456", db="web", autocommit=True ) cur = conn.cursor() sql = """ create table user_info( id int primary key auto_increnment not null, name varchar(32) not null, pwd varchar(32) not null """ cur.execute(sql) cur.close() conn.close()
main.py
from wsgiref.simple_server import make_server from urls import url_patterns def application(environ, start_response): start_response("200 OK", [("Content-type", "text/html")]) print(environ.get("PATH_INFO")) # 客户端请求路径 path = environ.get("PATH_INFO") # 方案1---直接针对路径做判断,然后写业务逻辑代码 # if path == "/login": # with open("login.html", "rb") as f: # data = f.read() # return [data] # elif path == "/index": # with open("index.html", "rb") as f: # data = f.read() # return [data] # 方案2---将业务处理逻辑封装成函数,与路径一一匹配放在元组,然后用一个列表放置所有的元组 # 这样就不用频繁的使用if判断,而且解耦后,如果想增加一个路径,只需要添加一个对应视图函数即可 # 把url_patterns(路由分发)列表放在urls.py # 把视图函数放在views.py # 把所有html文件放在templates文件夹下 func = None # 循环列表,取出路径和对应视图函数地址 for p, f in url_patterns: # 如果浏览器请求路径正确,那么把路径对应的视图函数地址赋值给func if path == p: func = f break # 如果func不为空,那么执行func,并且把客户端请求信息作为参数,返回func执行后的结果给客户端,如果为空则返回错误信息 if func: return [func(environ)] else: return [b"404 error"] httped = make_server("", 8080, application) httped.serve_forever()
urls.py
from views import *
url_patterns = [ ("/login", login), ("/reg", reg), ("/auth", auth), ]
views.py
import pymysql from urllib.parse import parse_qs def login(environ): with open("templates/login.html", "rb") as f: data = f.read() return data def reg(environ): with open("templates/reg.html", "rb") as f: data = f.read() return data def auth(environ): """ 以下操作是wsgiref模块读取form表单提交的数据,比Django复杂,但比我们自己处理起来要简单很多了 :param environ: :return: """ try: request_body_size = int(environ.get("CONTENT_LENGTH", 0)) except (ValueError): request_body_size = 0 request_body = environ['wsgi.input'].read(request_body_size) data = parse_qs(request_body) user = data.get(b"user")[0].decode("utf8") pwd = data.get(b"pwd")[0].decode("utf8") print(user, pwd) # 操作数据库 conn = pymysql.connect( host="127.0.0.1", port=3306, user="root", password="123456", db="web", ) cur = conn.cursor() sql = "select * from user_info where name=%s and pwd=%s;" cur.execute(sql, (user, pwd)) # 如果用户名密码正确,那么返回index页面,不正确返回错误信息 if cur.fetchone(): f = open("templates/index.html", "rb") data = f.read() return data else: return b"user or pwd is wrong"
login.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>登录</title> <link rel="icon" href="//www.jd.com/favicon.ico"> </head> <body> <h3>登录页面</h3> <!--向auth路径提交form表单--> <form action="http://127.0.0.1:8080/auth" method="post"> <p> 姓名: <input type="text" name="user"> </p> <p> 密码: <input type="password" name="pwd"> </p> <p> <input type="submit" value="提交"> </p> </form> </body> </html>
index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>首页</title> <link rel="icon" href="//www.jd.com/favicon.ico"> </head> <body> <h1>首页</h1> <img src="https://img0.baidu.com/it/u=2641803730,2025967347&fm=26&fmt=auto" alt=""> </body> </html>
总结
""" web框架功能总结 1. main.py:启动文件,封装了socket 2. urls.py:路径与视图函数映射关系---url控制器 3. views.py:视图函数,固定有一个形式参数environ(所有的请求信息都在这个参数里面,请求路径/请求方式/请求数据...)---视图函数 4. templates文件夹:html文件---模板 5. models:在项目启动前,在数据库中创建表结构---与数据库相关 """