自定义web框架
web框架
main.py: 启动文件,封装了socket
1 urls.py: 路径与视图函数映射关系 ---- url控制器
2 views.py 视图函数,固定有一个形式参数:environ -----视图函数,
3 templates文件夹: html文件 -----模板
4 models: 在项目启动前,在数据库中创建表结构 ----- 与数据库相关
如图所示:
main.py
1 # -*- coding: utf-8 -*- 2 # @Time : 2019/7/9 20:05 3 # @Author : Xiao 4 5 from wsgiref.simple_server import make_server 6 from urls import url_datas 7 8 def application(environ,start_response): 9 start_response('200 OK',[('Content-Type','text/html'),('Charset','utf8')]) 10 print("PATH", environ.get("PATH_INFO")) 11 # 当前请求路径 12 path = environ.get("PATH_INFO") 13 func = None 14 for item in url_datas: 15 if path == item[0]: 16 func = item[1] 17 break 18 if func: 19 return [func(environ)] 20 return [b'404!'] 21 22 server = make_server('',8080,application) 23 24 # 开始监听HTTP请求: 25 print('starting....') 26 server.serve_forever()
models.py
# -*- coding: utf-8 -*- # @Time : 2019/7/16 10:32 # @Author : Xiao from tools import Mysql sql_check_db = "show databases like 'oldboy';" sql_create_db = 'create database oldboy DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;' sql_check_table = 'show tables;' sql_create_table ='create table user_info(id int(10) PRIMARY KEY auto_increment,name VARCHAR(20),password VARCHAR(20),age int(10))' sql_check_data = 'select count(*) from oldboy' sql_create_data = "INSERT into user_info(name,password,age) values ('xg','a123456',18),('xk','a123456',38),('xh','a123456',28)" mysql_check = Mysql('localhost', 3306, 'root', 'root', charset="utf8") if mysql_check.exec_sql(sql_check_db): mysql_create = Mysql('localhost', 3306, 'root', 'root',dbname='oldboy', charset="utf8") if mysql_create.exec_sql(sql_check_table): if not mysql_create.exec_sql(sql_check_data): mysql_create.exec_sql(sql_create_data) else: mysql_create.exec_sql(sql_create_table) mysql_create.exec_sql(sql_create_data) else: mysql_check.exec_sql(sql_create_db) mysql_create = Mysql('localhost', 3306, 'root', 'root', dbname='oldboy', charset="utf8") mysql_create.exec_sql(sql_create_table) mysql_create.exec_sql(sql_create_data)
tools.py
# -*- coding: utf-8 -*- # @Time : 2019/7/16 10:42 # @Author : Xiao import pymysql class Mysql(object): def __init__(self, host, port, user, pwd, dbname="", charset="utf8"): """初始化数据库信息以及连接""" self.host = host self.port = port self.user = user self.pwd = pwd self.dbname = dbname self.charset = charset self.conn = None # 给析构函数用的,如果存在链接,则需要关闭链接,没有就不用管 self.conn = self.get_conn self.cur = None self.cur = self.get_cur @property def get_conn(self): """根据传参判断是否有传数据库名,然后做不同的链接操作""" try: if self.dbname: conn = pymysql.connect(host=self.host, port=self.port, user=self.user, password=self.pwd, database=self.dbname, charset=self.charset) return conn else: conn = pymysql.connect(host=self.host, port=self.port, user=self.user, password=self.pwd, charset=self.charset) return conn except Exception as e: print(e) @property def get_cur(self): """获取游标""" if self.conn: return self.conn.cursor() def exec_sql(self, sql, *args): """ 执行sql,根据不同的sql语法做不同的操作: 查询就返回查询结果列表,其他成功就返回受影响的行数整型,报错返回报错信息字符串 *args是为了防止sql注入,自己拼接的sql语法字符串可能被sql注入, 这里的用法是sql不需要自己拼接,直接将变量按顺序传进来,pymysql自动拼接,而且避免了sql注入的问题 如: sql = "insert into test.student VALUES (19,%s,'English',%s);" res = test_mysql.exec_sql(sql,"yangxga",100) """ try: rows = self.cur.execute(sql, args) # rows记录受影响的行 if sql.strip().lower().startswith('select') or sql.strip().lower().startswith('show'): res = self.cur.fetchall() res = self.format_res(res) print(res) return res else: self.conn.commit() # 非查询语句需要提交才能生效 res = rows print(res) return res except Exception as e: print(e) return e @staticmethod def format_res(res): """格式化数据库查找到的结果,如果""" res_lis = [] if res: for i in res: res_lis.append(i) return res_lis def __del__(self): """析构函数,关闭鼠标,断开连接""" if self.cur: self.cur.close() if self.conn: self.conn.close()
urls.py
# -*- coding: utf-8 -*- # @Time : 2019/7/9 20:05 # @Author : Xiao from views import * url_datas = [ ('/favicon.ico',favicon), ('/index',index), ('/login',login), ('/regist',regist) ]
views.py
# -*- coding: utf-8 -*- # @Time : 2019/7/9 20:17 # @Author : Xiao from tools import Mysql from urllib.parse import parse_qs def op_file(filename): with open(filename,'rb') as f: data = f.read() return data def favicon(environ): data = op_file('./templates/favicon.ico') return data def index(environ): data = op_file('./templates/index.html') return data def regist(environ): method = environ.get('REQUEST_METHOD').lower() if method == 'post': 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') if user.strip() and pwd.strip(): mysql_check = Mysql('localhost', 3306, 'root', 'root',dbname='oldboy', charset="utf8") sql = "select * from user_info WHERE name=%s" res = mysql_check.exec_sql(sql, user, pwd) if res and isinstance(res, list): data = b'username is already exits!' else: data = op_file('./templates/index.html') sql_reg = "insert into user_info(name,password) values(%s,%s);" mysql_check.exec_sql(sql_reg,user,pwd) else: data = b'username and password can not be empty!' else: data = op_file('./templates/register.html') return data def login(environ): method = environ.get('REQUEST_METHOD').lower() if method == 'post': 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') mysql_check = Mysql('localhost', 3306, 'root', 'root', dbname='oldboy', charset="utf8") sql = "select * from user_info WHERE name=%s and password=%s" res = mysql_check.exec_sql(sql, user, pwd) if res and isinstance(res,list): data = op_file('./templates/index.html') else: data = b'username or password is wrong!' else: data = op_file('./templates/login.html') return data
index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>首页</title> <style type="text/css"> h3{ margin: 10px 12px; float: left; overflow: hidden; } button{ margin: 12px; overflow: hidden; } </style> </head> <body> <h3>欢迎进入首页</h3> <button id="btn_reg">注册</button> <button id="btn_login">登陆</button> <form action=""> <img src="http://pic39.nipic.com/20140321/18063302_210604412116_2.jpg"> </form> </body> <script type="text/javascript"> window.onload = function () { var tmp_reg = document.getElementById('btn_reg'); var tmp_login = document.getElementById('btn_login'); tmp_reg.onclick = function () { window.open('http://127.0.0.1:8080/regist',target='_self') } tmp_login.onclick = function () { window.open('http://127.0.0.1:8080/login',target='_self') } } </script> </html>
login.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>登录</title> </head> <body> <h3>登录</h3> <form action="http://127.0.0.1:8080/login" method="post"> <label for="user">用户名:</label> <input type="text" name="user" id="user"> <label for="pwd">密码:</label> <input type="password" name="pwd" id="pwd"> <input type="submit" value="登录"> </form> </body> </html>
register.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>注册</title> </head> <body> <h3>注册</h3> <form action="http://127.0.0.1:8080/regist" method="post"> <label for="user">用户名:</label> <input type="text" name="user" id="user"> <label for="pwd">密码:</label> <input type="password" name="pwd" id="pwd"> <input type="submit" value="注册"> </form> </body> </html>