初识web框架
一、手写简易web框架
1. 获取输入网址后缀
conn, addr = server.accept() data = conn.recv(1024) data = data.decode('utf-8') current_path = data.split('\r\n')[0].split(' ')[1] print(current_path) conn.send(b'HTTP/1.1 200 ok\r\n\r\nhello world') conn.close()
2. 根据不同后缀返回不同结果
conn, addr = server.accept() data = conn.recv(1024) data = data.decode('utf-8') current_path = data.split('\r\n')[0].split(' ')[1] conn.send(b'HTTP/1.1 200 OK\r\n\r\n') if current_path == '/index': conn.send(b'index') elif current_path == '/login': conn.send(b'login') else: conn.send(b'hello world') conn.close()
3. 根据不同后缀返回不同html页面
conn, addr = server.accept() data = conn.recv(1024) conn.send(b'HTTP/1.1 200 OK\r\n\r\n') data = data.decode('utf-8') current_path = data.split('\r\n')[0].split(' ')[1] if current_path == '/index': with open(r'a.html', 'rb') as f: conn.send(f.read()) elif current_path == '/login': with open(r'b.html', 'rb') as f: conn.send(f.read()) else: conn.send(b'hello world') conn.close()
二、 wsgiref实现简易web框架
1. 往浏览器窗口返回固定值
from wsgiref.simple_server import make_server def run(env, response): print(env) response('200 ok', []) return [b'hello world'] if __name__ == '__main__': server = make_server('127.0.0.1', 8080, run) server.serve_forever()
2. 获取输入网址后缀
from wsgiref.simple_server import make_server def run(env, response): response('200 ok', []) current_path = env.get('PATH_INFO') print(current_path) return [b'hello world'] if __name__ == '__main__': server = make_server('127.0.0.1', 8080, run) server.serve_forever()
3. 根据不同后缀返回不同结果
from wsgiref.simple_server import make_server def run(env, response): response('200 ok', []) current_path = env.get('PATH_INFO') if current_path == '/index': return [b'index'] elif current_path == '/login': return [b'login'] return [b'404 error'] if __name__ == '__main__': server = make_server('127.0.0.1', 8080, run) server.serve_forever()
4. 根据不同后缀调用不同函数处理
from wsgiref.simple_server import make_server def index(env): return 'index' def login(env): return 'login' def errors(env): return '404' urls = [ ('/index', index), ('/login', login) ] def run(env, response): response('200 ok', []) current_path = env.get('PATH_INFO') func = None for url in urls: if url[0] == current_path: func = url[1] break if func: res = func(env) else: res = errors(env) return [res.encode('utf_8')] if __name__ == '__main__': server = make_server('127.0.0.1', 8080, run) server.serve_forever()
5. 将不同功能封装在不同模块中
1. main
from views import * from urls import urls from wsgiref.simple_server import make_server def run(env, response): response('200 ok', []) current_path = env.get('PATH_INFO') func = None for url in urls: if url[0] == current_path: func = url[1] break if func: res = func(env) else: res = errors(env) return [res.encode('utf_8')] if __name__ == '__main__': server = make_server('127.0.0.1', 8080, run) server.serve_forever()
2. views(视图函数)
def index(env): return 'index' def login(env): return 'login' def errors(env): return '404'
3. urls(路由与视图函数对应关系)
from views import * urls = [ ('/index', index), ('/login', login) ]
三、让页面展示当前时间
1. 在urls中添加对应关系
urls = [ ('/index', index), ('/login', login), ('/get_time', get_time), ]
2. 在templates中编写名为get_time的HTML模板
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script> </head> <body> $$time$$ </body> </html>
3. 在view中添加获取时间功能,将结果替换掉HTML页面中的字段。
def get_time(env): current_time = datetime.now().strftime('%Y-%m-%d %X') with open(r'templates/get_time.html', 'r', encoding='utf-8') as f: data = f.read() data = data.replace("$$time$$", current_time) return data
四、让页面展示字典
1. 在urls中添加对应关系
urls = [ ('/index', index), ('/login', login), ('/get_time', get_time), ('/get_user', get_user), ]
2. 在templates中编写名为get_time的HTML模板
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script> </head> <body> <p>{{data}}</p> <p>{{data['username']}}</p> <p>{{data.password}}</p> <p>{{data.get('hobby')}}</p> </body> </html>
3. 在views中导入jinja2模块,添加获取字典功能
from jinja2 import Template def get_user(env): user_dict = {'username': 'byx', 'password': '123', 'hobby': ['read', 'game', 'running']} with open(r'templates/get_user.html', 'r', encoding='utf-8') as f: data = f.read() temp = Template(data) res = temp.render(data=user_dict) return res
五、动态展示数据库
1. 在urls中添加对应关系
urls = [ ('/index', index), ('/login', login), ('/get_time', get_time), ('/get_user', get_user), ('/get_db', get_db) ]
2. 在templates中编写名为get_db的HTML模板
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script> <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script> <link rel="stylesheet" href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css"> </head> <body> <div class="container"> <div class="row"> <div class="col-md-8 col-md-offset-2"> <h2 class="text-center">用户数据展示</h2> <table class="table table-hover table-bordered table-striped"> <thead> <tr> <th>id</th> <th>username</th> <th>password</th> </tr> </thead> <tbody> {%for user_dict in user_list%} <tr> <td>{{user_dict.id}}</td> <td>{{user_dict.name}}</td> <td>{{user_dict.password}</td> </tr> {%endfor%} </tbody> </table> </div> </div> </div> </body> </html>
3. 在views中导入pymysql模块,连接数据库。通过jinja2模块导入get_db模板。
import pymysql def get_db(env): conn = pymysql.connect( host = '127.0.0.1', port = 3306, user = 'root', password = '123', database = 'test', charset = 'utf8', autocommit = True ) cursor = conn.cursor(pymysql.cursors.DictCursor) sql = 'select * from userinfo' affect_rows = cursor.execute(sql) data = cursor.fetchall() with open(r'templates/get_db.html', 'r', encoding='utf-8') as f: data1 = f.read() temp = Template(data1) res = temp.render(user_list=data) return res
六、总结