PythonWeb框架的本质

简单描述就是:浏览器通过你输入的网址给你的socket服务端发送请求,服务端接受到请求给其回复一个对应的html页面,这就是web项目。所有的Web应用本质上就是一个socket服务端,而用户的浏览器就是一个socket客户端,基于请求做出响应,客户都先请求,服务端做出对应的响应,按照http协议的请求协议发送请求,服务端按照http协议的响应协议来响应请求,这样的网络通信,我们就可以自己实现Web框架了。

什么是web框架?这就好比建设房子,房子主体钢结构等都为我们搭建好了,我们就是抹抹墙面,添加一些装饰,修饰一下即可。Django框架就是已经为我们搭建好的主题钢结构,剩下的根据不同的业务自定制即可。我们先自己搭建一个web框架,再对Django框架就会比较好理解了。

构建Socket服务器
  1. import socket
  2. server = socket.socket()
  3. server.bind(('127.0.0.1', 8002))
  4. server.listen()
  5. while 1:
  6. conn, addr = server.accept()
  7. while 1:
  8. client_data = conn.recv(1024).decode('utf-8')
  9. print(client_data)
  10. # 服务端与客户端建立联系必须要遵循一个协议,此时我们用http协议示例。
  11. conn.send('HTTP/1.1 200 OK \r\n\r\n'.encode('utf-8'))
  12. conn.send('<h1>hello</h1>'.encode('utf-8'))
  13. conn.close()

我们通过浏览器请求服务端,服务端给我们返回一个hello标签,客户请求过来之后,要想让服务端给客户端返回消息,必须基于一个协议,我们用http协议示例,那么服务端如果如何返回给浏览器一个页面尼?

构建一个html页面返回
  1. <!DOCTYPE html>
  2. <html lang="zh-CN">
  3. <head>
  4. <meta charset="utf-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1">
  7. <style>
  8. div{
  9. background-color: #7fb8f7;
  10. color: red;
  11. }
  12. </style>
  13. </head>
  14. <body>
  15. <div>你好,世界</div>
  16. </body>
  17. </html>

此时我们的服务端必须将html页面返回给客户端,可以通过读取文件然后发送bytes数据

服务端

  1. import socket
  2. server = socket.socket()
  3. server.bind(('127.0.0.1',8002))
  4. server.listen()
  5. while 1:
  6. conn,addr = server.accept()
  7. while 1:
  8. client_data = conn.recv(1024).decode('utf-8')
  9. print(client_data)
  10. # 服务端与客户端建立联系必须要遵循一个协议,此时我们用http协议示例
  11. conn.send('HTTP/1.1 200 OK \r\n\r\n'.encode('utf-8'))
  12. with open('Day11/index.html',mode='rb') as f1:
  13. conn.send(f1.read())
  14. conn.close()

我们浏览器访问服务端会发现我们服务器会接受以下信息

  1. GET / HTTP/1.1
  2. Host: 127.0.0.1:8002
  3. Connection: keep-alive
  4. Upgrade-Insecure-Requests: 1
  5. User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.162 Safari/537.36
  6. Sec-Fetch-Dest: document
  7. Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
  8. Sec-Fetch-Site: none
  9. Sec-Fetch-Mode: navigate
  10. Sec-Fetch-User: ?1
  11. Accept-Encoding: gzip, deflate, br
  12. Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
http协议工作原理

以下是HTTP请求/响应的步骤

  1. # 1. 客户端连接到Web服务器
  2. # 一个HTTP客户端,通常是浏览器,与Web服务器的HTTP端口(默认为80)建立一个TCP套接字连接。例如,http://www.baidu.com
  3. # 2. 发送HTTP请求
  4. # 通过TCP套接字,客户端向Web服务器发送一个文本的请求报文,一个请求报文由请求行、请求头部、空行和请求数据4部分组成。
  5. # 3. 服务器接收请求并返回HTTP响应
  6. # Web服务器解析请求,定位请求资源。服务器将资源复本写到TCP套接字,由客户端读取。一个响应由状态行、响应头部、空行和响应数据4部分组成。
  7. # 4. 释放连接TCP连接
  8. # 若connection 模式为close,则服务器主动关闭TCP连接,客户端被动关闭连接,释放TCP连接;若connection 模式为keepalive,则该连接会保持一段时间,在该时间内可以继续接收请求;
  9. # 5. 客户端浏览器解析HTML内容
  10. # 客户端浏览器首先解析状态行,查看表明请求是否成功的状态代码。然后解析每一个响应头,响应头告知以下为若干字节的HTML文档和文档的字符集。客户端浏览器读取响应数据HTML,根据HTML的语法对其进行格式化,并在浏览器窗口中显示。
  11. # 如果问浏览器输入URL,按下回车经历以下流程
  12. # 1. 浏览器向 DNS 服务器请求解析该 URL 中的域名所对应的 IP 地址;
  13. # 2. 解析出 IP 地址后,根据该 IP 地址和默认端口 80,和服务器建立TCP连接;
  14. # 3. 浏览器发出读取文件(URL 中域名后面部分对应的文件)的HTTP 请求,该请求报文作为 TCP 三次握手的第三个报文的数据发送给服务器;
  15. # 4. 服务器对浏览器请求作出响应,并把对应的 html 文本发送给浏览器;
  16. # 5. 释放 TCP连接;
  17. # 6. 浏览器将该 html 文本并显示内容;  
常用的HTTP方法

HTTP/1.1协议中共定义了八种方法(也叫“动作”)来以不同方式操作指定的资源:

  1. # GET
  2. # 向指定的资源发出“显示”请求。使用GET方法应该只用在读取数据,而不应当被用于产生“副作用”的操作中,例如在Web Application中。其中一个原因是GET可能会被网络蜘蛛等随意访问。
  3. # HEAD
  4. # 与GET方法一样,都是向服务器发出指定资源的请求。只不过服务器将不传回资源的本文部分。它的好处在于,使用这个方法可以在不必传输全部内容的情况下,就可以获取其中“关于该资源的信息”(元信息或称元数据)。
  5. # POST
  6. # 向指定资源提交数据,请求服务器进行处理(例如提交表单或者上传文件)。数据被包含在请求本文中。这个请求可能会创建新的资源或修改现有资源,或二者皆有。
  7. # PUT
  8. # 向指定资源位置上传其最新内容。
  9. # DELETE
  10. # 请求服务器删除Request-URI所标识的资源。
  11. # TRACE
  12. # 回显服务器收到的请求,主要用于测试或诊断。
  13. # OPTIONS
  14. # 这个方法可使服务器传回该资源所支持的所有HTTP请求方法。用'*'来代替资源名称,向Web服务器发送OPTIONS请求,可以测试服务器功能是否正常运作。
  15. # CONNECT
  16. # HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。通常用于SSL加密服务器的链接(经由非加密的HTTP代理服务器)。
  17. # 注意事项:
  18. # 方法名称是区分大小写的。当某个请求所针对的资源不支持对应的请求方法的时候,服务器应当返回状态码405(Method Not Allowed),当服务器不认识或者不支持对应的请求方法的时候,应当返回状态码501(Not Implemented)。
  19. # HTTP服务器至少应该实现GET和HEAD方法,其他方法都是可选的。当然,所有的方法支持的实现都应当匹配下述的方法各自的语义定义。此外,除了上述方法,特定的HTTP服务器还能够扩展自定义的方法。例如PATCH(由 RFC 5789 指定的方法)用于将局部修改应用到资源。
  20. # 请求方式: get与post请求(通过form表单我们自己写写看)
  21. # GET提交的数据会放在URL之后,也就是请求行里面,以?分割URL和传输数据,参数之间以&相连,如EditBook?name=test1&id=123456.(请求头里面那个content-type做的这种参数形式,后面讲) POST方法是把提交的数据放在HTTP包的请求体中.
  22. # GET提交的数据大小有限制(因为浏览器对URL的长度有限制),而POST方法提交的数据没有限制.
  23. # GET与POST请求在服务端获取请求数据方式不同,就是我们自己在服务端取请求数据的时候的方式不同了,这句废话昂。
HTTP状态码
  1. # 状态代码的第一个数字代表当前响应的类型:
  2. # 1xx消息——请求已被服务器接收,继续处理
  3. # 2xx成功——请求已成功被服务器接收、理解、并接受
  4. # 3xx重定向——需要后续操作才能完成这一请求
  5. # 4xx请求错误——请求含有词法错误或者无法被执行
  6. # 5xx服务器错误——服务器在处理某个正确请求时发生错误

构建Web框架

简单版Web框架

test1.html

  1. <!DOCTYPE html>
  2. <html lang="zh-CN">
  3. <head>
  4. <meta charset="utf-8">
  5. <style>
  6. div {
  7. background-color: #7fb8ff;
  8. font-size: 16px;
  9. }
  10. </style>
  11. </head>
  12. <body>
  13. <div>欢迎访问xx商城</div>
  14. <ul>
  15. <li>aa</li>
  16. <li>bb</li>
  17. <li>cc</li>
  18. </ul>
  19. </body>
  20. </html>

test1.py

  1. import socket
  2. server = socket.socket()
  3. server.bind(('127.0.0.1',8001))
  4. server.listen()
  5. while 1:
  6. conn,addr = server.accept()
  7. client_data = conn.recv(1024).decode('utf-8')
  8. print(client_data)
  9. # 服务端与客户端建立联系必须要遵循一个协议,此时我们用http协议示例
  10. conn.send('HTTP/1.1 200 OK \r\nk1:v1\r\n\r\n'.encode('utf-8'))
  11. with open('test1.html',mode='rb') as f1:
  12. conn.send(f1.read())
  13. conn.close()
升级版Web框架

html

  1. <!DOCTYPE html>
  2. <html lang="zh-CN">
  3. <head>
  4. <meta charset="utf-8">
  5. <link rel="stylesheet" href="test2.css">
  6. <link rel="icon" href="2.jpg">
  7. </head>
  8. <body>
  9. <div>欢迎访问和软商城</div>
  10. <ul>
  11. <li>aa</li>
  12. <li>bb</li>
  13. <li>cc</li>
  14. </ul>
  15. <img src="2.jpg" alt="美女">
  16. <script src="test2.js"></script>
  17. </body>
  18. </html>

浏览器执行到link标签时,href会发出一个请求,请求你当前根目录下面的test2.css文件,其实完整url也就是http://127.0.0.1:8001/test2.css,你引入js同理,此过程是异步的,html代码不会等你引入完css之后再执行下面代码

test2.css

  1. div {
  2. background-color: #7fb8ff;
  3. font-size: 16px;
  4. }

test2.js

alert('未满18岁禁止入内');

test2.py

  1. import socket
  2. server = socket.socket()
  3. server.bind(('127.0.0.1',8001))
  4. server.listen()
  5. while 1:
  6. conn,addr = server.accept()
  7. client_data = conn.recv(1024)
  8. request_path = client_data.decode('utf-8').split('\r\n')[0].split()[1]
  9. # 服务端与客户端建立联系必须要遵循一个协议,此时我们用http协议示例
  10. conn.send('HTTP/1.1 200 OK \r\nk1:v1\r\n\r\n'.encode('utf-8'))
  11. if request_path == '/':
  12. with open('test2.html',mode='rb') as f1:
  13. conn.send(f1.read())
  14. elif request_path == '/test2.css':
  15. with open('test2.css',mode='rb') as f1:
  16. conn.send(f1.read())
  17. elif request_path == '/2.jpg':
  18. with open('2.jpg',mode='rb') as f1:
  19. conn.send(f1.read())
  20. elif request_path == '/test2.js':
  21. with open('test2.js',mode='rb') as f1:
  22. conn.send(f1.read())
  23. conn.close()
函数版Web框架

上一个版本比较Low,并且代码应该整合成函数而不能使用纯面向过程方式,所以我们进行改版

test3.html

css,js,img都用上个版本的

  1. <!DOCTYPE html>
  2. <html lang="zh-CN">
  3. <head>
  4. <meta charset="utf-8">
  5. <link rel="stylesheet" href="test2.css">
  6. <link rel="icon" href="2.jpg">
  7. </head>
  8. <body>
  9. <div>欢迎访问和软商城</div>
  10. <ul>
  11. <li>aa</li>
  12. <li>bb</li>
  13. <li>cc</li>
  14. </ul>
  15. <img src="2.jpg" alt="美女">
  16. <script src="test2.js"></script>
  17. </body>
  18. </html>

test3.py

  1. import socket
  2. server = socket.socket()
  3. server.bind(('127.0.0.1', 8001))
  4. server.listen()
  5. def html(conn):
  6. with open('test3.html', mode='rb') as f1:
  7. conn.send(f1.read())
  8. conn.close()
  9. def css(conn):
  10. with open('test2.css', mode='rb') as f1:
  11. conn.send(f1.read())
  12. conn.close()
  13. def jpg(conn):
  14. with open('2.jpg', mode='rb') as f1:
  15. conn.send(f1.read())
  16. conn.close()
  17. def js(conn):
  18. with open('test2.js', mode='rb') as f1:
  19. conn.send(f1.read())
  20. conn.close()
  21. request_list = [
  22. ('/', html),
  23. ('/test2.css', css),
  24. ('/2.jpg', jpg),
  25. ('/test2.js', js),
  26. ]
  27. while 1:
  28. conn, addr = server.accept()
  29. client_data = conn.recv(1024)
  30. request_path = client_data.decode('utf-8').split('\r\n')[0].split()[1]
  31. # 服务端与客户端建立联系必须要遵循一个协议,此时我们用http协议示例。
  32. conn.send('HTTP/1.1 200 OK \r\nk1:v1\r\n\r\n'.encode('utf-8'))
  33. for i in request_list:
  34. if request_path == i[0]:
  35. i[1](conn)
  36. conn.close()

虽然这个版本简介明了,但是还不完美,现在虽然是异步处理请求,但是我们可以通过并发让异步请求用并发处理更加合理

并发版Web框架

test4.html

  1. <!DOCTYPE html>
  2. <html lang="zh-CN">
  3. <head>
  4. <meta charset="utf-8">
  5. <link rel="stylesheet" href="test2.css">
  6. <link rel="icon" href="2.jpg">
  7. </head>
  8. <body>
  9. <div>欢迎访问和软商城</div>
  10. <ul>
  11. <li>aa</li>
  12. <li>bb</li>
  13. <li>cc</li>
  14. </ul>
  15. <img src="2.jpg" alt="美女">
  16. <script src="test2.js"></script>
  17. </body>
  18. </html>

test4.py

  1. import socket
  2. from threading import Thread
  3. server = socket.socket()
  4. server.bind(('127.0.0.1', 8001))
  5. server.listen()
  6. def html(conn):
  7. with open('test3.html', mode='rb') as f1:
  8. conn.send(f1.read())
  9. conn.close()
  10. def css(conn):
  11. with open('test2.css', mode='rb') as f1:
  12. conn.send(f1.read())
  13. conn.close()
  14. def jpg(conn):
  15. with open('2.jpg', mode='rb') as f1:
  16. conn.send(f1.read())
  17. conn.close()
  18. def js(conn):
  19. with open('test2.js', mode='rb') as f1:
  20. conn.send(f1.read())
  21. conn.close()
  22. request_list = [
  23. ('/', html),
  24. ('/test2.css', css),
  25. ('/2.jpg', jpg),
  26. ('/test2.js', js),
  27. ]
  28. while 1:
  29. conn, addr = server.accept()
  30. client_data = conn.recv(1024)
  31. request_path = client_data.decode('utf-8').split('\r\n')[0].split()[1]
  32. print(request_path)
  33. # 服务端与客户端建立联系必须要遵循一个协议,此时我们用http协议示例。
  34. conn.send('HTTP/1.1 200 OK \r\nk1:v1\r\n\r\n'.encode('utf-8'))
  35. for i in request_list:
  36. if request_path == i[0]:
  37. t = Thread(target=i[1],args=(conn,))
  38. t.start()
  39. # conn.close()
动态版Web框架

一般情况下,我们的数据都是在数据库中,动态获取,实时变化,但现在我们模拟一下数据,利用时间戳

test5.html

  1. <!DOCTYPE html>
  2. <html lang="zh-CN">
  3. <head>
  4. <meta charset="utf-8">
  5. <link rel="stylesheet" href="test2.css">
  6. <link rel="icon" href="2.jpg">
  7. </head>
  8. <body>
  9. <div>欢迎访问和软商城</div>
  10. <ul>
  11. <li>aa</li>
  12. <li>bb</li>
  13. <li>cc</li>
  14. </ul>
  15. <img src="2.jpg" alt="美女">
  16. <script src="test2.js"></script>
  17. </body>
  18. </html>

test5.py

  1. import socket
  2. from threading import Thread
  3. import time
  4. server = socket.socket()
  5. server.bind(('127.0.0.1', 8001))
  6. server.listen()
  7. def html(conn):
  8. time_now = time.strftime('%Y/%m/%d %H:%M:%S',time.localtime())
  9. with open('test5.html',encoding='utf-8') as f1:
  10. data = f1.read().format(time_now=time_now)
  11. conn.send(data.encode('utf-8'))
  12. conn.close()
  13. def css(conn):
  14. with open('test2.css', mode='rb') as f1:
  15. conn.send(f1.read())
  16. conn.close()
  17. def jpg(conn):
  18. with open('2.jpg', mode='rb') as f1:
  19. conn.send(f1.read())
  20. conn.close()
  21. def js(conn):
  22. with open('test2.js', mode='rb') as f1:
  23. conn.send(f1.read())
  24. conn.close()
  25. request_list = [
  26. ('/', html),
  27. ('/test2.css', css),
  28. ('/2.jpg', jpg),
  29. ('/test2.js', js),
  30. ]
  31. while 1:
  32. conn, addr = server.accept()
  33. client_data = conn.recv(1024)
  34. request_path = client_data.decode('utf-8').split('\r\n')[0].split()[1]
  35. print(request_path)
  36. # 服务端与客户端建立联系必须要遵循一个协议,此时我们用http协议示例。
  37. conn.send('HTTP/1.1 200 OK \r\nk1:v1\r\n\r\n'.encode('utf-8'))
  38. for i in request_list:
  39. if request_path == i[0]:
  40. t = Thread(target=i[1],args=(conn,))
  41. t.start()
  42. # conn.close()
wsgiref模板版+数据库Web框架

wsgiref模块其实就是将整个请求信息给封装了起来,就不需要你自己处理了,假如它将所有请求信息封装成了一个叫做request的对象,那么你直接request.path就能获取到用户这次请求的路径,request.method就能获取到本次用户请求的请求方式(get还是post)等,那这个模块用起来,我们再写web框架是不是就简单了好多啊

对于真实开发中的python web程序来说,一般会分为两部分:服务器程序和应用程序.

服务器程序负责对socket服务器进行封装,并在请求到来时,对请求的各种数据进行整理。

  应用程序则负责具体的逻辑处理。为了方便应用程序的开发,就出现了众多的Web框架,例如:Django、Flask、web.py 等。不同的框架有不同的开发方式,但是无论如何,开发出的应用程序都要和服务器程序配合,才能为用户提供服务。

  这样,服务器程序就需要为不同的框架提供不同的支持。这样混乱的局面无论对于服务器还是框架,都是不好的。对服务器来说,需要支持各种不同框架,对框架来说,只有支持它的服务器才能被开发出的应用使用。最简单的Web应用就是先把HTML用文件保存好,用一个现成的HTTP服务器软件,接收用户请求,从文件中读取HTML,返回。如果要动态生成HTML,就需要把上述步骤自己来实现。不过,接受HTTP请求、解析HTTP请求、发送HTTP响应都是苦力活,如果我们自己来写这些底层代码,还没开始写动态HTML呢,就得花个把月去读HTTP规范。

  正确的做法是底层代码由专门的服务器软件实现,我们用Python专注于生成HTML文档。因为我们不希望接触到TCP连接、HTTP原始请求和响应格式,所以,需要一个统一的接口协议来实现这样的服务器软件,让我们专心用Python编写Web业务。

  这时候,标准化就变得尤为重要。我们可以设立一个标准,只要服务器程序支持这个标准,框架也支持这个标准,那么他们就可以配合使用。一旦标准确定,双方各自实现。这样,服务器可以支持更多支持标准的框架,框架也可以使用更多支持标准的服务器。

  WSGI(Web Server Gateway Interface)就是一种规范,它定义了使用Python编写的web应用程序与web服务器程序之间的接口格式,实现web应用程序与web服务器程序间的解耦。

  常用的WSGI服务器有uwsgi、Gunicorn。而Python标准库提供的独立WSGI服务器叫wsgiref,Django开发环境用的就是这个模块来做服务器。

接下来我们先看一看wsgiref的简单用法:

  1. from wsgiref.simple_server import make_server
  2. # wsgiref本身就是个web框架,提供了一些固定的功能(请求和响应信息的封装,
  3. # 不需要我们自己写原生的socket了也不需要咱们自己来完成请求信息的获取了,提取起来很方便
  4. # 函数名字随便起
  5. def application(environ,start_response):
  6. '''
  7. :param environ: 是全部加工好的请求信息,加工成了一个字典,通过字典取值的方式就能拿到很多你想要拿到的信息
  8. :param start_response: 帮你封装响应信息的(响应行和响应头),注意下面的参数
  9. :return:
  10. '''
  11. start_response('200 OK',[('k1','v1'),])
  12. print(environ)
  13. print(environ['PATH_INFO'])
  14. return [b'<h1>Hello,Web!</h1>']
  15. # 类似socketserver
  16. httpd = make_server('127.0.0.1',8080,application)
  17. print('Servering HTTP on port 8080...')
  18. # 开始监听HTTP请求
  19. httpd.serve_forever()

这个模块就是封装好服务器程序的处理,方便你使用。

接下来我们引入数据库内容,首先创建一个数据库,然后在插入一些数据:

mysql安装请看我博客mysql标签里面,此处不做介绍

my.cnf

  1. [root@mysql-test ~]# cat /etc/my.cnf
  2. [mysql]
  3. default-character-set=utf8
  4. [mysqld]
  5. datadir=/var/lib/mysql
  6. socket=/var/lib/mysql/mysql.sock
  7. symbolic-links=0
  8. character-set-server=utf8
  9. default-storage-engine=INNODB
  10. max_connections=200
  11. log-error=/var/log/mysqld.log
  12. pid-file=/var/run/mysqld/mysqld.pid
  13. [client]
  14. password = ZHOUjian.24
  15. user = root

socket服务端

  1. from wsgiref.simple_server import make_server
  2. import time
  3. def html(conn):
  4. time_now = time.strftime('%Y/%m/%d %H:%M:%S', time.localtime())
  5. with open('test5.html', encoding='utf-8') as f1:
  6. data = f1.read().format(time_now=time_now)
  7. conn.send(data.encode('utf-8'))
  8. conn.close()
  9. def css(conn):
  10. with open('test2.css', mode='rb') as f1:
  11. data = f1.read()
  12. return data
  13. def jpg(conn):
  14. with open('2.jpg', mode='rb') as f1:
  15. data = f1.read()
  16. return data
  17. def js(conn):
  18. with open('test2.js', mode='rb') as f1:
  19. data = f1.read()
  20. return data
  21. request_list = [
  22. ('/', html),
  23. ('/test2.css', css),
  24. ('/2.jpg', jpg),
  25. ('/test2.js', js),
  26. ]
  27. def application(environ, start_response):
  28. start_response('200 OK', [('k1', 'v1'), ('k2', 'v2')])
  29. print(environ)
  30. request_path = environ['PATH_INFO']
  31. for i in request_list:
  32. if request_path == i[0]:
  33. ret = i[1]()
  34. return [ret]
  35. else:
  36. return [b'<h1>404.....</h1>']
  37. httpd = make_server('127.0.0.1', 8080, application)
  38. print('Serving HTTP on port 8080...')
  39. # 开始监听HTTP请求:
  40. httpd.serve_forever()

pymysql1.py(创建数据)

  1. import pymysql
  2. conn = pymysql.connect("121.36.43.223", "admin", "ZHOUjian.21")
  3. cursor = conn.cursor(pymysql.cursors.DictCursor)
  4. # 创建 webtest数据库
  5. cursor.execute('create database webtest;')
  6. # 创建userinfo数据库表
  7. cursor.execute('create table webtest.userinfo(id int,name varchar(20),age int);')
  8. cursor.execute("""
  9. insert into webtest.userinfo(id,name,age) values
  10. (1,'幽梦',18),
  11. (2,'flying',19),
  12. (3,'渐渐',20);
  13. """
  14. )
  15. conn.commit()
  16. cursor.close()
  17. conn.close()

pymysql2.py(getdata)

  1. import pymysql
  2. def get_data():
  3. conn = pymysql.connect("121.36.43.223", "admin", "ZHOUjian.21")
  4. cursor = conn.cursor(pymysql.cursors.DictCursor)
  5. cursor.execute("select * from webtest.userinfo;")
  6. data = cursor.fetchone()
  7. conn.commit()
  8. cursor.close()
  9. conn.close()
  10. return data
wsgiref模块版+数据库+jinja2 web框架

上面的代码实现了一个简单的动态页面(字符串替换),我完全可以从数据库中查询数据,然后去替换我html中的对应内容(专业名词叫做模板渲染,你先渲染一下,再给浏览器进行渲染),然后再发送给浏览器完成渲染。 这个过程就相当于HTML模板渲染数据。 本质上就是HTML内容中利用一些特殊的符号来替换要展示的数据。 我这里用的特殊符号是我定义的,其实模板渲染有个现成的工具: jinja2,DJango有自带的模版渲染方法,和jinja2很像,但是只能适用于Django框架,而jinja2可以适用于多种框架。

下载

pip install jinja2

getdata

  1. import pymysql
  2. def get_data():
  3. conn = pymysql.connect("121.36.43.223", "admin", "ZHOUjian.21")
  4. cursor = conn.cursor(pymysql.cursors.DictCursor)
  5. cursor.execute("select * from webtest.userinfo;")
  6. data = cursor.fetchone()
  7. conn.commit()
  8. cursor.close()
  9. conn.close()
  10. return data

test7.html

  1. <!DOCTYPE html>
  2. <html lang="zh-CN">
  3. <head>
  4. <meta charset="utf-8">
  5. <link rel="stylesheet" href="test2.css">
  6. <link rel="icon" href="2.jpg">
  7. </head>
  8. <body>
  9. <div>欢迎访问和软商城</div>
  10. <div>{time_now}</div>
  11. <ul>
  12. <li>aa</li>
  13. <li>bb</li>
  14. <li>cc</li>
  15. </ul>
  16. <img src="2.jpg" alt="美女">
  17. <script src="test2.js"></script>
  18. </body>
  19. </html>

socket服务端

  1. from threading import Thread
  2. from wsgiref.simple_server import make_server
  3. from Day15.pymysql2 import showdata
  4. from jinja2 import Template
  5. def html(conn):
  6. userinfo_data = showdata()
  7. print(userinfo_data)
  8. with open('test7.html', 'rb',encoding='utf-8') as f1:
  9. data = f1.read()
  10. temp = Template(data)
  11. print(temp)
  12. data = temp.reader({'userinfo':userinfo_data})
  13. data = data.encode('utf-8')
  14. return data
  15. def css(conn):
  16. with open('test2.css','rb') as f1:
  17. data = f1.read()
  18. return data
  19. def jpg(conn):
  20. with open('2.jpg','rb') as f1:
  21. data = f1.read()
  22. return data
  23. def js(conn):
  24. with open('test2.js','rb') as f1:
  25. data = f1.read()
  26. return data
  27. urlpatterns = [
  28. ('/', html),
  29. ('/test2.css', css),
  30. ('/2.jpg', jpg),
  31. ('/test2.js', js),
  32. ]
  33. def application(environ, start_response):
  34. # print(environ)
  35. # conn.send(b'HTTP/1.1 200 ok\r\n\r\nxxxx')
  36. start_response('200 OK', [('k1','v1'),('k2','v2')])
  37. # print(environ['PATH_INFO'])
  38. path = environ['PATH_INFO']
  39. for i in urlpatterns:
  40. if path == i[0]:
  41. ret = i[1]()
  42. break
  43. else:
  44. ret = b'404 not found!!!!'
  45. return [ret]
  46. httpd = make_server('127.0.0.1', 8080, application)
  47. print('Serving HTTP on port 8080...')
  48. httpd.serve_forever()

此处有问题,等我大概过一遍回来再弄细节

15 . PythonWeb框架本质的更多相关文章

  1. python---web框架本质(1)

    总的来说php相对较为简单,但是内部封装太多,不利于对编程的更本质探索. 但是对于生产开发确实是一门不错的语言.python对于socket以及web框架的理解更加透彻 # coding:utf8 # ...

  2. python---web框架本质(2)

    目录 controllers //存放控制方法 models //存放模型方法 views //存放视图模板 index.html new.html show.html index.py //用户访问 ...

  3. Python开发【第十四篇】:Web框架本质

    Web框架本质 众所周知,对于所有的Web应用,本质上其实就是一个socket服务端,用户的浏览器其实就是一个socket客户端. ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ...

  4. Web 框架本质解析

    一  Web框架本质 1. 自己开发Web框架 - socket - http协议 - HTML知识 - 数据库(pymysql,SQLAlchemy) HTTP: 无状态.短连接 TCP: 不断开 ...

  5. Django _web框架本质

    Web框架本质 我们可以这样理解:所有的Web应用本质上就是一个socket服务端,而用户的浏览器就是一个socket客户端. 这样我们就可以自己实现Web框架了. socket服务端 import  ...

  6. Web框架本质

    Web框架本质 众所周知,对于所有的Web应用,本质上其实就是一个socket服务端,用户的浏览器其实就是一个socket客户端. #!/usr/bin/env python #coding:utf- ...

  7. Python自动化运维之26、Web框架本质、MVC与MTV

    一.Web框架本质 众所周知,对于所有的Web应用,本质上其实就是一个socket服务端,用户的浏览器其实就是一个socket客户端. #!/usr/bin/env python #coding:ut ...

  8. Web框架本质及第一个Django实例

    Web框架本质 我们可以这样理解:所有的Web应用本质上就是一个socket服务端,而用户的浏览器就是一个socket客户端. 这样我们就可以自己实现Web框架了. 半成品自定义web框架 impor ...

  9. Web框架本质及第一个Django实例 Web框架

    Web框架本质及第一个Django实例   Web框架本质 我们可以这样理解:所有的Web应用本质上就是一个socket服务端,而用户的浏览器就是一个socket客户端. 这样我们就可以自己实现Web ...

随机推荐

  1. libevent(六)http server

    客户端: #include <stdio.h> #include <stdlib.h> #include <string.h> #include <signa ...

  2. 如何将项目上传至GitHub?

    心血来潮的一天,突然想写点什么哈哈哈哈. 那就写写如何将项目上传到GitHub(矫情,上传个项目还要写个文章) 第一步:下载Git https://git-scm.com/download/win 下 ...

  3. boost在Qt中的使用

    一.说明 理论上,Qt和boost是同等级别的C++库,如果使用Qt,一般不会需要再用boost,但是偶尔也会有特殊情况,比如,第三方库依赖等等.本文主要介绍boost在windows Qt(MinG ...

  4. MySQL 入门(3):事务隔离

    摘要 在这一篇内容中,我将从事务是什么开始,聊一聊事务的必要性. 然后,介绍一下在InnoDB中,四种不同级别的事务隔离,能解决什么问题,以及会带来什么问题. 最后,我会介绍一下InnoDB解决高并发 ...

  5. 【基础】excel如何根据数据内容显示不同颜色。

    需求: 店柜完成率排名相比上阶段升降,升显示绿色“↑“,降显示红色“↓”,持平显示黑色“-”. 步骤: 第一步 先计算两次排名的差值(本次排名-上次排名). 第二步 对差值列设置单元格格式,设置格式如 ...

  6. 使用Python创建一个系统监控程序--李渣渣(lizaza.cn)

    最近在做个人网站,但是由于服务器资源不足,偶尔会出现系统崩溃的现象,所以想写一个程序来实时监控系统状态.当系统资源占用过高时发送邮件提醒. psutil(进程和系统实用程序)是一个跨平台的库,用于检索 ...

  7. myeclipse 2017 CI 破解

    1.首先下载破解文件(破解前先关闭myeclipse),链接:https://pan.baidu.com/s/1CPFH4Nga3xITSyj-BCVeaw 提取码:mkvz 2.将下载的破解文件解压 ...

  8. docker容器与系统时间同步最佳方法

    前言:在Docker容器创建好之后,可能会发现容器时间跟宿主机时间不一致,此时需要同步它们的时间,让容器时间跟宿主机时间保持一致. 一.分析时间不一致的原因 宿主机采用了CST时区,CST应该是指(C ...

  9. jQuery的面试题

    1.$的原理 答案: 1)$("选择器")是先查找DOM元素,再将DOM元素放入jQuery对象中 其中自带优化: 如果选择器是#id,则自动调用getElementById 如果 ...

  10. SpringBoot切面Aop的demo简单讲解

    前言 本篇文章主要介绍的是SpringBoot切面Aop的demo简单讲解. SpringBoot Aop 说明:如果想直接获取工程那么可以直接跳到底部,通过链接下载工程代码. 切面(Aop) 一.概 ...