Django前置知识--手撕框架(一):https://developer.aliyun.com/article/1495494
重启服务端,浏览器再次访问,页面内容有了,样式效果也有了
检查查看application里面该有的数据也都有了,浏览器可以正常渲染页面了
浏览器检查network里面的筛选,可以看到浏览器的各种文件请求,以及服务器响应耗时
每个文件点进去,可以查看具体请求信息和响应
请求
响应
这种方法比较low,如果网站页面比较多的话,客户端请求比较多,一个一个判断,说不过去。开发中,尽量少用多层判断,判断越少越好
需要改进
函数版
import socket #改造服务端,针对客户端不同的请求,服务端回复不同的内容 tcp_server = socket.socket() #端口复用 tcp_server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,True) tcp_server.bind(("127.0.0.1",8898)) tcp_server.listen(128) #首先先将页面信息封装成函数,返回相关页面文件信息流 def html(): with open("beautiful.html", "rb") as fp: data = fp.read() return data def css(): with open("xx.css", "rb") as fp: data = fp.read() return data def jpg(): with open("1.jpg", "rb") as fp: data = fp.read() return data def js(): with open("xx.js", "rb") as fp: data = fp.read() return data #将函数与请求对应 urlpath = [ ("/",html), ("/xx.css",css), ("/1.jpg",jpg), ("/xx.js",js), ] while True: # 获取连接对象和客户端ip和端口 conn,adddr = tcp_server.accept() # 接收客户端数据 res = conn.recv(1024) from_broswer = res.decode() print(from_broswer) #根据请求头 GET / HTTP/1.1 以空格为分隔符,取索引为1的数据,即为客户端请求的服务端内容 path = from_broswer.split()[1] # 针对不同请求赋值不同页面数据,发送个客户端 for i in urlpath: if path == i[0]: data = i[1]() break # 发送协议数据 strvar = "HTTP/1.1 200 0k\r\n\r\n" conn.send(strvar.encode()) # 发送给客户端页面 conn.send(data) conn.close() #tcp_server.close();
但是该页面都是静态页面,下面做个动态页面
html页面加个h1标签
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>个人中心</title> <link rel="stylesheet" href="xx.css"> </head> <body> <h1>欢迎来到32期spa会所</h1> <h1>%时间%</h1> <div class="c1"></div> <img src="1.jpg" alt=""> </body> <script src="xx.js"></script> </html>
在服务端,将页面上的 %时间% 替换为一个动态获取的时间戳
时间戳默认是float
import socket import time #改造服务端,针对客户端不同的请求,服务端回复不同的内容,动态页面版 tcp_server = socket.socket() #端口复用 tcp_server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,True) tcp_server.bind(("127.0.0.1",8898)) tcp_server.listen(128) #展示动态页面,以r的形式读取 def html(): 将时间戳转换成字符串,时间戳默认是float类型 now = str(time.time()) with open("beautiful.html", "r",encoding="utf-8") as fp: data = fp.read() 在这里将页面上的 %时间% 替换为动态的时间戳 data = data.replace("%时间%",now).encode() return data def css(): with open("xx.css", "rb") as fp: data = fp.read() return data def jpg(): with open("1.jpg", "rb") as fp: data = fp.read() return data def js(): with open("xx.js", "rb") as fp: data = fp.read() return data #将函数与请求对应 urlpath = [ ("/",html), ("/xx.css",css), ("/1.jpg",jpg), ("/xx.js",js), ] while True: # 获取连接对象和客户端ip和端口 conn,adddr = tcp_server.accept() # 接收客户端数据 res = conn.recv(1024) from_broswer = res.decode() print(from_broswer) #根据请求头 GET / HTTP/1.1 以空格为分隔符,取索引为1的数据,即为客户端请求的服务端内容 path = from_broswer.split()[1] # 针对不同请求赋值不同页面数据,发送个客户端 for i in urlpath: if path == i[0]: data = i[1]() break # 发送协议数据 strvar = "HTTP/1.1 200 0k\r\n\r\n" conn.send(strvar.encode()) # 发送给客户端页面 conn.send(data) conn.close() #tcp_server.close();
但这只是单个页面网站,人家网站都有好多页面可以跳转,需要改造
2、多页面网站框架
我们的之所以是单页面,原因就是只有一个beautiful.html
要实现多页面,多添加几个html页面即可
我们新加一个person.html
服务端将页面添加进去,其他不变
浏览器访问,可以跳转到指定页面
我们可以在主页面做个页面跳转
<!-- 页面跳转,相对路径,当点击该链接时,浏览器拼接请求url http://127.0.0.1:8898/person 实现页面跳转-->
重启服务器,浏览页面
点击跳转,实现想要结果
现在,请求时异步的,但服务端是客户端来了一个个请求,建立连接,收发数据,断开连接,下次请求过来,又重新建立连接…
服务端是同步的,不能异步回复
客户端异步发送的请求,异步回复多好,需要改进
3、多线程并发服务端框架
import socket import time from threading import Thread #多线程编程,服务端实现异步回复客户端 tcp_server = socket.socket() #端口复用 tcp_server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,True) tcp_server.bind(("127.0.0.1",8898)) tcp_server.listen(128) #每个函数自己发送数据给客户端,发送完毕自己断开连接。每个函数是一个线程 def html(conn): now = str(time.time()) with open("beautiful.html", "r",encoding="utf-8") as fp: data = fp.read() data = data.replace("%时间%",now).encode() # 发送给客户端页面 conn.send(data) conn.close() def css(conn): with open("xx.css", "rb") as fp: data = fp.read() # 发送给客户端页面 conn.send(data) conn.close() def jpg(conn): with open("1.jpg", "rb") as fp: data = fp.read() # 发送给客户端页面 conn.send(data) conn.close() def js(conn): with open("xx.js", "rb") as fp: data = fp.read() # 发送给客户端页面 conn.send(data) conn.close() #添加个页面 def person(conn): with open("person.html", "rb") as fp: data = fp.read() # 发送给客户端页面 conn.send(data) conn.close() #将函数与请求对应,将person加入 urlpath = [ ("/",html), ("/xx.css",css), ("/1.jpg",jpg), ("/xx.js",js), ("/person",person) ] #多线程编程 if __name__ == '__main__': while True: # 获取连接对象和客户端ip和端口 conn,adddr = tcp_server.accept() # 接收客户端数据 res = conn.recv(1024) from_broswer = res.decode() print(from_broswer) #根据请求头 GET / HTTP/1.1 以空格为分隔符,取索引为1的数据,即为客户端请求的服务端内容 path = from_broswer.split()[1] # 针对不同请求赋值不同页面数据,发送个客户端 # 发送协议数据 strvar = "HTTP/1.1 200 0k\r\n\r\n" conn.send(strvar.encode()) # 针对每个请求,采用一个线程 for i in urlpath: if path == i[0]: 针对每个页面请求,创建一个线程,将连接作为参数传给函数 t = Thread(target=i[1],args=(conn,)) t.start() break # tcp_server.close();
多线程,理论上更快了。我们的页面比较小,体现不出来
现在,我们每个功能都在一个文件里面,当业务量比较庞大时,就比较冗余
因此,我们需要做功能拆分
1、manager
import socket from threading import Thread import urls #多线程编程,服务端实现异步回复客户端 tcp_server = socket.socket() #端口复用 tcp_server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,True) tcp_server.bind(("127.0.0.1",8898)) tcp_server.listen(128) #多线程编程 if __name__ == '__main__': while True: # 获取连接对象和客户端ip和端口 conn,adddr = tcp_server.accept() # 接收客户端数据 res = conn.recv(1024) from_broswer = res.decode() print(from_broswer) #根据请求头 GET / HTTP/1.1 以空格为分隔符,取索引为1的数据,即为客户端请求的服务端内容 path = from_broswer.split()[1] # 针对不同请求赋值不同页面数据,发送个客户端 # 发送协议数据 strvar = "HTTP/1.1 200 0k\r\n\r\n" conn.send(strvar.encode()) # 针对每个请求,采用一个线程 for i in urls.urlpath: if path == i[0]: t = Thread(target=i[1],args=(conn,)) t.start() break # tcp_server.close();
2、urls
import views #将函数与请求对应,将person加入 urlpath = [ ("/",views.html), ("/static/xx.css",views.css), ("/static/1.jpg",views.jpg), ("/static/xx.js",views.js), ("/person",views.person) ]
3、views
import time #展示动态页面,以r的形式读取 def html(conn): now = str(time.time()) with open("templates/beautiful.html", "r", encoding="utf-8") as fp: data = fp.read() data = data.replace("%时间%",now).encode() # 发送给客户端页面 conn.send(data) conn.close() def css(conn): with open("static/xx.css", "rb") as fp: data = fp.read() # 发送给客户端页面 conn.send(data) conn.close() def jpg(conn): with open("static/1.jpg", "rb") as fp: data = fp.read() # 发送给客户端页面 conn.send(data) conn.close() def js(conn): with open("static/xx.js", "rb") as fp: data = fp.read() # 发送给客户端页面 conn.send(data) conn.close() #添加个页面 def person(conn): with open("templates/person.html", "rb") as fp: data = fp.read() # 发送给客户端页面 conn.send(data) conn.close()
templates目录下存放html文件
beatuiful.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>个人中心</title> <link rel="stylesheet" href="../static/xx.css"> </head> <body> <h1>欢迎来到32期spa会所</h1> <!-- 页面跳转,相对路径,当点击该链接时,浏览器拼接请求url http://127.0.0.1:8898/person 实现页面跳转--> <a href="/person">个人中心</a> <h1>%时间%</h1> <div class="c1"></div> <img src="../static/1.jpg" alt=""> </body> <script src="../static/xx.js"></script> </html>
person.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>个人中心</title> </head> <body> <h1>这是个人中心页面</h1> </body> </html>
static目录下存放css,js,图片文件等静态文件
可以创建个文件连接数据库
models.py
import pymysql def MySqlInfo(): conn = pymysql.connect( host="10.10.0.52", port=3306, database="kuangjia", charset="utf8mb4", user="root", password="Jinghao31357@" ) cur = conn.cursor(cursor=pymysql.cursors.DictCursor) try: sql = "create table userinfo(id int primary key auto_increment, name char(10) not null, age int unsigned);" cur.execute(sql) print("创建表成功") except BaseException as e: print("有异常,执行失败",e) finally: #pymysql默认是不提交的,手动设置每次执行后提交 conn.commit() cur.close() conn.close()
创建个wsgi存放我们的manager.py核心代码,并封装成一个函数里面,其他不用动
在manager.py文件中编写代码运行方式
import sys from wsgi import run from models import MySqlInfo commands = sys.argv tasks = commands[1] #运行项目的指令: python manage.py runserver #数据库同步指令: python manage.py migrate if tasks == "runserver": run() elif tasks == "migrate": MySqlInfo()
1、配置路径对应的函数关系 urls.py文件中,有参考案例
2、在views.py中,写视图函数
3、templates文件夹中创建html文件
框架开发出来不是给客户用的,是给程序员使用的
然后写个readme
比如我们这个框架,各个模块拆分,就比较清晰了。这就是django的雏形