Web框架本质
所有的web服务本质都是一个socket服务端,用户浏览器就是一个socket客户端,这样就实现了自己的web框架 ,但是自己的写的框架肯定很low,各种工能崩溃,所以我们就要学习python强大的Django 框架
首先我们要自己一步步写一个框架,用来辅助理解Django的原理
import socket import time sk = socket.socket() sk.bind(("127.0.0.1", 8080)) # 绑定IP和端口 sk.listen() # 监听 # 将返回不同的内容部分封装成函数 def index(url): with open("index.html", "r", encoding="utf8") as f: s = f.read() now = str(time.time()) s = s.replace("@@oo@@", now) return bytes(s, encoding="utf8") def home(url): with open("home.html", "r", encoding="utf8") as f: s = f.read() return bytes(s, encoding="utf8") # 定义一个url和实际要执行的函数的对应关系 list1 = [ ("/index/", index), ("/home/", home), ] while 1: # 等待连接 conn, add = sk.accept() data = conn.recv(8096) # 接收客户端发来的消息 # 从data中取到路径 data = str(data, encoding="utf8") # 把收到的字节类型的数据转换成字符串 # 按 分割 data1 = data.split(" ")[0] url = data1.split()[1] print("url:", url) print("*" * 120) # 是换行;Content-Type:是响应类型格式 ;text/html 表示网页 # HTTP/1.1 200 OK 所用的协议 conn.send(b'HTTP/1.1 200 OK Content-Type: text/html; charset=utf-8 ') # 因为要遵循HTTP协议 # 根据不同的路径返回不同内容 func = None for i in list1: if i[0] == url: func = i[1] break if func: response = func(url) else: response = b"404 not found!" # 具体的响应体 conn.send(response) conn.close()
wsgiref
WSGI(Web Server Gateway Interface)就是一种规范,它定义了使用Python编写的web应用程序与web服务器程序之间的接口格式,实现web应用程序与web服务器程序间的解耦。
常用的WSGI服务器有uwsgi、Gunicorn。而Python标准库提供的独立WSGI服务器叫wsgiref,Django开发环境用的就是这个模块来做服务器
import time from wsgiref.simple_server import make_server # 将返回不同的内容部分封装成函数 def index(url): with open("index.html", "r", encoding="utf8") as f: s = f.read() now = str(time.time()) s = s.replace("@@oo@@", now) return bytes(s, encoding="utf8") def home(url): with open("home.html", "r", encoding="utf8") as f: s = f.read() return bytes(s, encoding="utf8") # 定义一个url和实际要执行的函数的对应关系 list1 = [ ("/index/", index), ("/home/", home), ] def run_server(environ, start_response): start_response('200 OK', [('Content-Type', 'text/html;charset=utf8'), ]) # 设置HTTP响应的状态码和头信息 url = environ['PATH_INFO'] # 取到用户输入的url func = None for i in list1: if i[0] == url: func = i[1] break if func: response = func(url) else: response = b"404 not found!" return [response, ] if __name__ == '__main__': httpd = make_server('127.0.0.1', 8090, run_server) print("Serving HTTP on port 8090...") httpd.serve_forever()
jinja2
HTML模板渲染数据,本质上就是HTML内容中利用一些特殊的符号来替换要展示的数据。 我这里用的特殊符号是我定义的,其实模板渲染有个现成的工具:jinja2
首先安装:pip install jinja2
import time from wsgiref.simple_server import make_server import jinja2 # 将返回不同的内容部分封装成函数 def index(url): with open("index.html", "r", encoding="utf8") as f: s = f.read() now = str(time.time()) s = s.replace("@@oo@@", now) return bytes(s, encoding="utf8") def home(url): with open("home.html", "r", encoding="utf8") as f: s = f.read() return bytes(s, encoding="utf8") def xiaoqiang(url): with open("xiaoqiang.html", "r", encoding="utf8") as f: s = f.read() template = jinja2.Template(s) # 生成一个jinja2的Template(模板)对象 data = {"name": "小强", "hobby_list": ["对子哈特", "姑娘", "大汉"]} response = template.render(data) # 本质上是完成了字符串的替换 return bytes(response, encoding="utf8") # 定义一个url和实际要执行的函数的对应关系 list1 = [ ("/index/", index), ("/home/", home), ("/xiaoqiang/", xiaoqiang), ] def run_server(environ, start_response): start_response('200 OK', [('Content-Type', 'text/html;charset=utf8'), ]) # 设置HTTP响应的状态码和头信息 url = environ['PATH_INFO'] # 取到用户输入的url func = None for i in list1: if i[0] == url: func = i[1] break if func: response = func(url) else: response = b"404 not found!" return [response, ] if __name__ == '__main__': httpd = make_server('127.0.0.1', 8090, run_server) print("Serving HTTP on port 8090...") httpd.serve_forever()
现在的数据是我们自己手写的,我们也可以从数据库中查询数据
使用pymysql连接数据库:
conn = pymysql.connect(host="127.0.0.1", port=3306, user="root", passwd="xxx", db="xxx", charset="utf8") cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) cursor.execute("select name, age, department_id from userinfo") user_list = cursor.fetchall() cursor.close() conn.close()
import time from wsgiref.simple_server import make_server import jinja2 import pymysql # 将返回不同的内容部分封装成函数 def index(url): with open("index.html", "r", encoding="utf8") as f: s = f.read() now = str(time.time()) s = s.replace("@@oo@@", now) return bytes(s, encoding="utf8") def home(url): with open("home.html", "r", encoding="utf8") as f: s = f.read() return bytes(s, encoding="utf8") def xiaoqiang(url): with open("xiaoqiang.html", "r", encoding="utf8") as f: s = f.read() template = jinja2.Template(s) # 生成一个jinja2的Template(模板)对象 # data = {"name": "小强", "hobby_list": ["对子哈特", "姑娘", "大汉"]} conn = pymysql.connect(host="127.0.0.1", port=3306, user="root", passwd="123456", db="userinfo", charset="utf8") cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) cursor.execute("SELECT name, hobby FROM user") user = cursor.fetchone() cursor.close() conn.close() print("user:", user) print("*" * 120) hobby_list = user["hobby"].split() user["hobby_list"] = hobby_list print(user) print("-" * 120) response = template.render(user) # 本质上是完成了字符串的替换 return bytes(response, encoding="utf8") # 定义一个url和实际要执行的函数的对应关系 list1 = [ ("/index/", index), ("/home/", home), ("/xiaoqiang/", xiaoqiang), ] def run_server(environ, start_response): start_response('200 OK', [('Content-Type', 'text/html;charset=utf8'), ]) # 设置HTTP响应的状态码和头信息 url = environ['PATH_INFO'] # 取到用户输入的url func = None for i in list1: if i[0] == url: func = i[1] break if func: response = func(url) else: response = b"404 not found!" return [response, ] if __name__ == '__main__': httpd = make_server('127.0.0.1', 8090, run_server) print("Serving HTTP on port 8090...") httpd.serve_forever()