1.HTTP协议|web框架
1、web应用
Web应用程序是一种可以通过Web访问的应用程序,程序的最大好处是用户很容易访问应用程序,用户只需要有浏览器即可,不需要再安装其他软件。应用程序有两种模式C/S、B/S。C/S是客户端/服务器端程序,也就是说这类程序一般独立运行。而B/S就是浏览器端/服务器端应用程序,这类应用程序一般借助谷歌,火狐等浏览器来运行。WEB应用程序一般是B/S模式。Web应用程序首先是“应用程序”,和用标准的程序语言,如java,python等编写出来的程序没有什么本质上的不同。在网络编程的意义下,浏览器是一个socket客户端,服务器是一个socket服务端。
web框架
Web框架(Web framework)是一种开发框架,用来支持动态网站、网络应用和网络服务的开发。这大多数的web框架提供了一套开发和部署网站的方式,也为web行为提供了一套通用的方法。web框架已经实现了很多功能,开发人员使用框架提供的方法并且完成自己的业务逻辑,就能快速开发web应用了。浏览器和服务器的是基于HTTP协议进行通信的。也可以说web框架就是在以上十几行代码基础上扩展出来的,有很多简单方便使用的方法,大大提高了开发的效率。
wsgiref模块
最简单的Web应用就是先把HTML用文件保存好,用一个现成的HTTP服务器软件,接收用户请求,从文件中读取HTML,返回。
如果要动态生成HTML,就需要把上述步骤自己来实现。不过,接受HTTP请求、解析HTTP请求、发送HTTP响应都是苦力活,如果我们自己来写这些底层代码,还没开始写动态HTML呢,就得花个把月去读HTTP规范。
正确的做法是底层代码由专门的服务器软件实现,我们用Python专注于生成HTML文档。因为我们不希望接触到TCP连接、HTTP原始请求和响应格式,所以,需要一个统一的接口协议来实现这样的服务器软件,让我们专心用Python编写Web业务。这个接口就是WSGI :Web Server Gateway Interface。而wsgiref 模块就是python基于wsgi协议开发的服务模块。
from wsgiref.simple_server import make_ser
遵循http协议,字符串必须按照某种格式发给浏览器。
最简单的web请求过程:
服务端server
import socket sock = socket.socket() sock.bind(('127.0.0.1',8800)) sock.listen(5) while 1: print('server waiting') conn,addr = sock.accept() #请求 data = conn.recv(1024) #拿到请求信息 print("data",data) <h1> Hello luffycity </h1> conn.send(b"HTTP/1.1 200 OK\r\n\r\nHello luffycity!") #与浏览器的通讯,要遵循HTTP协议去发送请求数据,浏览器也会按这种协议进行解析;200是显示状态码, conn.close() #前面为响应首行,后边是响应体,以\r\n两个空格隔开。 打印: server waiting data b'GET / HTTP/1.1\r\nHost: 127.0.0.1:8800\r\nConnection: keep-alive\r\nUser-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.75 Safari/537.36\r\nUpgrade-Insecure-Requests: 1\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8\r\nAccept-Encoding: gzip, deflate, br\r\nAccept-Language: zh-CN,zh;q=0.9\r\nCookie: csrftoken=Mrqe5gm2pfaQy6LqXAJDqcWWU3BfTFrB0LMMhAEv2Pi0STKVn95bR6ODrDPZn34j\r\n\r\n' server waiting data b'GET /favicon.ico HTTP/1.1\r\nHost: 127.0.0.1:8800\r\nConnection: keep-alive\r\nUser-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.75 Safari/537.36\r\nAccept: image/webp,image/apng,image/*,*/*;q=0.8\r\nReferer: http://127.0.0.1:8800/\r\nAccept-Encoding: gzip, deflate, br\r\nAccept-Language: zh-CN,zh;q=0.9\r\nCookie: csrftoken=Mrqe5gm2pfaQy6LqXAJDqcWWU3BfTFrB0LMMhAEv2Pi0STKVn95bR6ODrDPZn34j\r\n\r\n' server waiting
import socket sock = socket.socket() sock.bind(('127.0.0.1',8800)) sock.listen(5) while 1: print('server waiting') conn,addr = sock.accept() data = conn.recv(1024) print("data",data) #################读取html文件;直接返回一个html页面################## with open('index.html','rb')as f: data = f.read() conn.send((b"HTTP/1.1 200 OK\r\n\r\n%s"%data)) conn.close() 打印:(get请求) server waiting #第一个/ 为路径部分; GET / HTTP/1.1 为请求体;以换行符\r\n把他们隔开,都是一个个头-请求头;两个\r\n\r\n后边就是请求体 data b'GET / HTTP/1.1\r\nHost: 127.0.0.1:8800\r\nConnection: keep-alive\r\nCache-Control: max-age=0\r\nUpgrade-Insecure-Requests: 1\r\nUser-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.75 Safari/537.36\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8\r\nAccept-Encoding: gzip, deflate, br\r\nAccept-Language: zh-CN,zh;q=0.9\r\nCookie: csrftoken=Mrqe5gm2pfaQy6LqXAJDqcWWU3BfTFrB0LMMhAEv2Pi0STKVn95bR6ODrDPZn34j\r\n\r\n' server waiting
data b'GET /kris?name=kris&age=22 HTTP/1.1\r\nHost: 127.0.0.1:8800\r\nConnection: keep-alive\r\nUser-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.75 Safari/537.36\r\nUpgrade-Insecure-Requests: 1\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8\r\nAccept-Encoding: gzip, deflate, br\r\nAccept-Language: zh-CN,zh;q=0.9\r\nCookie: sessionid=4sr81dc29tzw0gb1h2zxoqvumbbe6u1z; csrftoken=i1XjCb7mAKefMkNzUUqIvjHpL598C6IC8V0u0AKkPdh03eL7NzPvExLSBE1eLxOA\r\n\r\n' data b'GET /favicon.ico HTTP/1.1\r\nHost: 127.0.0.1:8800\r\nConnection: keep-alive\r\nUser-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.75 Safari/537.36\r\nAccept: image/webp,image/apng,image/*,*/*;q=0.8\r\nReferer: http://127.0.0.1:8800/\r\nAccept-Encoding: gzip, deflate, br\r\nAccept-Language: zh-CN,zh;q=0.9\r\nCookie: csrftoken=Mrqe5gm2pfaQy6LqXAJDqcWWU3BfTFrB0LMMhAEv2Pi0STKVn95bR6ODrDPZn34j\r\n\r\n' server waiting
####################Html文件代码################
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>Hello Luffycity!</h1> <img src="https://gss0.bdstatic.com/-4o3dSag_xI4khGkpoWK1HF6hhy/baike/w%3D268%3Bg%3D0/sign=16535fed6163f6241c5d3e05bf7f8cc5/fd039245d688d43f63d84526771ed21b0ff43bf5.jpg"> <a href="http://www.luffycity.com">路飞学城</a> </body> </html>
post请求
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="http://127.0.0.1:8800/" method="post"> 用户名<input type="text" name="user"> 密码<input type="password" name="pwd"> <input type="submit"> </form> </body> </html>
import socket sock = socket.socket() sock.bind(('127.0.0.1',8800)) sock.listen(5) while 1: print('server waiting') conn,addr = sock.accept() data = conn.recv(1024) # print("data",data) #读取html文件 with open('login.html','rb')as f: data = f.read() conn.send((b"HTTP/1.1 200 OK\r\n\r\n%s"%data)) conn.close() 打印:(post请求) server waiting 请求首行,请求头、请求头、......,请求数据 data b'GET / HTTP/1.1\r\nHost: 127.0.0.1:8800\r\nConnection: keep-alive\r\nUser-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.75 Safari/537.36\r\nUpgrade-Insecure-Requests: 1\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8\r\nAccept-Encoding: gzip, deflate, br\r\nAccept-Language: zh-CN,zh;q=0.9\r\nCookie: csrftoken=Mrqe5gm2pfaQy6LqXAJDqcWWU3BfTFrB0LMMhAEv2Pi0STKVn95bR6ODrDPZn34j\r\n\r\n' server waiting data b'GET /favicon.ico HTTP/1.1\r\nHost: 127.0.0.1:8800\r\nConnection: keep-alive\r\nUser-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.75 Safari/537.36\r\nAccept: image/webp,image/apng,image/*,*/*;q=0.8\r\nReferer: http://127.0.0.1:8800/\r\nAccept-Encoding: gzip, deflate, br\r\nAccept-Language: zh-CN,zh;q=0.9\r\nCookie: csrftoken=Mrqe5gm2pfaQy6LqXAJDqcWWU3BfTFrB0LMMhAEv2Pi0STKVn95bR6ODrDPZn34j\r\n\r\n' server waiting data b'' server waiting data b'' server waiting data b'' server waiting data b'' server waiting data b'POST / HTTP/1.1\r\nHost: 127.0.0.1:8800\r\nConnection: keep-alive\r\nContent-Length: 20\r\nCache-Control: max-age=0\r\nOrigin: http://127.0.0.1:8800\r\nUpgrade-Insecure-Requests: 1\r\nContent-Type: application/x-www-form-urlencoded\r\nUser-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.75 Safari/537.36\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8\r\nReferer: http://127.0.0.1:8800/\r\nAccept-Encoding: gzip, deflate, br\r\nAccept-Language: zh-CN,zh;q=0.9\r\nCookie: csrftoken=Mrqe5gm2pfaQy6LqXAJDqcWWU3BfTFrB0LMMhAEv2Pi0STKVn95bR6ODrDPZn34j\r\n\r\nuser=egon&pwd=abc123' server waiting data b'GET /favicon.ico HTTP/1.1\r\nHost: 127.0.0.1:8800\r\nConnection: keep-alive\r\nUser-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.75 Safari/537.36\r\nAccept: image/webp,image/apng,image/*,*/*;q=0.8\r\nReferer: http://127.0.0.1:8800/\r\nAccept-Encoding: gzip, deflate, br\r\nAccept-Language: zh-CN,zh;q=0.9\r\nCookie: csrftoken=Mrqe5gm2pfaQy6LqXAJDqcWWU3BfTFrB0LMMhAEv2Pi0STKVn95bR6ODrDPZn34j\r\n\r\n' server waiting
请求首行
请求头 请求头 请求头 .... 请求体(a=1&b=2) # 注意:只有POST请求才会有请求体 b'GET / HTTP/1.1\r\nHost: 127.0.0.1:8880\r\nConnection: keep-alive\r\nUpgrade-Insecure-Requests: 1\r\nUser-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8\r\nAccept-Encoding: gzip, deflate, br\r\nAccept-Language: zh-CN,zh;q=0.9,en;q=0.8\r\nCookie: csrftoken=IU9cIEWdRzTx7gm6JIjASm9TZJSve8jUGcfXPbgTXpSW0iHot1NOxpjdroESRB4f\r\n\r\n' b'GET /yuan?name=yuan&age=22 HTTP/1.1\r\nHost: 127.0.0.1:8880\r\nConnection: keep-alive\r\nUpgrade-Insecure-Requests: 1\r\nUser-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8\r\nAccept-Encoding: gzip, deflate, br\r\nAccept-Language: zh-CN,zh;q=0.9,en;q=0.8\r\nCookie: csrftoken=IU9cIEWdRzTx7gm6JIjASm9TZJSve8jUGcfXPbgTXpSW0iHot1NOxpjdroESRB4f\r\n\r\n' b'POST / HTTP/1.1\r\nHost: 127.0.0.1:8880\r\nConnection: keep-alive\r\nContent-Length: 20\r\nPragma: no-cache\r\nCache-Control: no-cache\r\nOrigin: http://127.0.0.1:8880\r\nUpgrade-Insecure-Requests: 1\r\nContent-Type: application/x-www-form-urlencoded\r\nUser-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8\r\nReferer: http://127.0.0.1:8880/\r\nAccept-Encoding: gzip, deflate, br\r\nAccept-Language: zh-CN,zh;q=0.9,en;q=0.8\r\nCookie: csrftoken=IU9cIEWdRzTx7gm6JIjASm9TZJSve8jUGcfXPbgTXpSW0iHot1NOxpjdroESRB4f\r\n\r\nuser=bisheng&pwd=456' URL: 协议://IP:端口(80)/路径?a=1&b=2
?之前的都是路径,?之后的为请求数据
2、http协议简介
特性:
http协议是基于TCP/IP协议之上的应用层协议;
基于请求响应模式:先从客户端开始建立通信的,服务器端在没有 接收到请求之前不会发送响应;
无状态保持:HTTP是一种不保存状态,即无状态(stateless)协议,HTTP协议 自身不对请求和响应之间的通信状态进行保存,也就是说在HTTP这个级别,协议对于发送过的请求或响应都不做持久化处理。
使用HTTP协议,每当有新的请求发送时,就会有对应的新响应产 生。协议本身并不保留之前一切的请求或响应报文的信息。这是为了更快地处理大量事务,确保协议的可伸缩性,而特意把HTTP协议设计成 如此简单的。可是,随着Web的不断发展,因无状态而导致业务处理变得棘手 的情况增多了。比如,用户登录到一家购物网站,即使他跳转到该站的 其他页面后,也需要能继续保持登录状态。针对这个实例,网站为了能 够掌握是谁送出的请求,需要保存用户的状态。HTTP/1.1虽然是无状态协议,但为了实现期望的保持状态功能, 于是引入了Cookie技术。有了Cookie再用HTTP协议通信,就可以管 理状态了。
无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。
请求协议与响应协议
http协议包含由浏览器发送数据到服务器需要遵循的请求协议与服务器发送数据到浏览器需要遵循的请求协议。用于HTTP协议交互的信被为HTTP报文。请求端(客户端)的HTTP报文 做请求报文,响应端(服务器端)的 做响应报文。HTTP报文本身是由多行数据构成的字 文本。
请求协议:请求报文的构成见下
get请求没有请求体,会放在url后面;只有post请求才有请求体;
请求方式: get与post请求
-
GET提交的数据会放在URL之后,以?分割URL和传输数据,参数之间以&相连,如EditBook?name=test1&id=123456. POST方法是把提交的数据放在HTTP包的请求体中.
-
GET提交的数据大小有限制(因为浏览器对URL的长度有限制),而POST方法提交的数据没有限制.
响应协议
响应格式:
响应状态码
重定向(地址搬家了,换成另外一个域名了。)
3.web框架
wsgi接口协议,基于接口实现的wsgiref
.ico是浏览器发的一个图标请求;
图标请求
wsgiref到底为我们做了什么事情?(解析数据和封装数据)
.拿到的那个字符串data就是根据Http协议封装好的,怎么解析它,拿到路径和数据信息呢??
按照http协议解包, dict/obj d={"path":"/login"} #d.get("path") # 按着http请求协议解析数据 # 专注与web业务开发 # path=d.get("path") 取到当前请求的路径, # # if path=="/login": # return login.html # 按着http响应协议封装数据 (组装Http响应格式,才能返回数据)
wsgiref模块
最简单的Web应用就是先把HTML用文件保存好,用一个现成的HTTP服务器软件,接收用户请求,从文件中读取HTML,返回。
如果要动态生成HTML,就需要把上述步骤自己来实现。不过,接受HTTP请求、解析HTTP请求、发送HTTP响应都是苦力活,如果我们自己来写这些底层代码,还没开始写动态HTML呢,就得花个把月去读HTTP规范。
正确的做法是底层代码由专门的服务器软件实现,我们用Python专注于生成HTML文档。因为我们不希望接触到TCP连接、HTTP原始请求和响应格式,所以,需要一个统一的接口协议来实现这样的服务器软件,让我们专心用Python编写Web业务。这个接口就是WSGI:Web Server Gateway Interface。而wsgiref模块就是python基于wsgi协议开发的服务模块。
把data数据解析成environ字典;start_response和return共同组成一个相应体。
from wsgiref.simple_server import make_server def application(environ, start_response): #请求来了就用application来处理,回调函数;按着http协议解析数据所有的数据:把data数据解析成了environ这个字典;按这http协议进行组装数据,格式就是按照这种start_response来给我们处理格式 #按着http协议解析数据:environ;按着http协议组装数据:start_response
start_response('200 OK', [('Content-Type','text/html')]) #这里边放一个字符串(响应首行,'200 OK'),一个列表(响应头,可以为空);状态码、响应头 print("PATH", environ.get("PATH_INFO")) path = environ.get("PATH_INFO") #获得当前请求路径 if path == "/favicon.ico": '''return [b"hello favicon.ico"] #浏览器想得到一个图片你却给了它个字符串''' with open("favicon.ico",'rb') as f: data = f.read() return [data] return [b'<h1>Hello,web!</h1>'] #响应数据;响应首行、响应头、响应数据这3个(start_response和return)共同组成一个响应体; httpd = make_server('', 8080, application) #封装的socket;make_server要实例化下,传参实例化一个类对象; id地址、端口,调用application回调函数 print('Serving HTTP on port 8000.。') #开始监听HTTP请求: httpd.serve_forever() #等待用户链接:conn,addr=sock.accept();一旦请求进来它就回去调用application(environ,start_response)函数 打印: Serving HTTP on port 8000.。 PATH /kris 127.0.0.1 - - [24/May/2018 17:48:56] "GET /kris HTTP/1.1" 200 19 127.0.0.1 - - [24/May/2018 17:48:56] "GET /favicon.ico HTTP/1.1" 200 25214 PATH /favicon.ico
方案一:
from wsgiref.simple_server import make_server def application(environ, start_response): #请求来了就用application来处理;所有的数据都在environ这个字典里,start_response来给我们处理格式 start_response('200 OK', [('Content-Type','text/html')]) #状态码、响应头 print("PATH", environ.get("PATH_INFO")) path = environ.get("PATH_INFO") if path == "/favicon.ico": #浏览器发的图标请求; '''return [b"hello favicon.ico"] #浏览器想得到一个图片你却给了它个字符串''' hello favicon.ico,不应该返回一个字符串 with open("favicon.ico",'rb') as f: #把图标文件打开。 data = f.read() return [data] elif path == "/login": with open("login.html","rb")as f: data = f.read() return [data] #wsgiref规定的返回的必须是字节数据; elif path == "/index": with open("index.html","rb")as f: data = f.read() return [data] return [b'<h1>Hello,web!</h1>'] httpd = make_server('', 8080, application) #封装的socket print('Serving HTTP on port 8000.。') #开始监听HTTP请求: httpd.serve_forever() #打印: Serving HTTP on port 8000.。 PATH /index 127.0.0.1 - - [24/May/2018 18:00:55] "GET /index HTTP/1.1" 200 394 127.0.0.1 - - [24/May/2018 18:07:08] "GET /index/login HTTP/1.1" 200 19 PATH /index/login PATH /login 127.0.0.1 - - [24/May/2018 18:07:21] "GET /login HTTP/1.1" 200 363
方案2 改善
from wsgiref.simple_server import make_server def login(): #给它加个参数environ,下面传了你就要接收这个参数。给它传请求接收信息,它用不用的到再说;如想获取当前请求方式,请求数据都在environ这个字典里边。 with open("login.html","rb")as f: data = f.read() return data def index(): #environ with open("index.html","rb")as f: data = f.read() return data def favi(): #environ with open("favicon.ico", "rb")as f: data = f.read() return data #你们返回数据data,我把数据data返回到列表里即[func()] def reg(): #environ with open("regs.html", "rb")as f: data = f.read() return data def application(environ, start_response): #请求来了就用application来处理;所有的数据都在environ这个字典里,start_response来给我们处理格式 start_response('200 OK', [('Content-Type','text/html')]) #状态码、响应头 print("PATH", environ.get("PATH_INFO")) #当前请求路径 path = environ.get("PATH_INFO") #解耦 #再多加个路径,给它加个元组就可以了。 url_patterns = [ ("/login", login), ("/regs", reg), ("/index", index), ("/favicon.ico",favi) ] func = None for item in url_patterns: if path == item[0]: #item[0] ---->> /login /regs /index /favicon.ico func = item[1] #跟上边的匹配成功了,执行这个函数就可以了。 break if func: #func默认为None,都匹配不成功还是为None;func一旦有值,说明某次匹配成功了 return [func()] #返回个列表;函数执行了都有返回值,把函数的返回值data数据加到列表里边去; 给它加个参数environ即请求信息,必须给你传上,你函数用到就拿 else: return [b'404!'] httpd = make_server('', 8080, application) #封装的socket print('Serving HTTP on port 8000.。') #开始监听HTTP请求: httpd.serve_forever() 打印:(与浏览器的交互) Serving HTTP on port 8000.。 PATH / 127.0.0.1 - - [24/May/2018 18:31:58] "GET / HTTP/1.1" 200 4 127.0.0.1 - - [24/May/2018 18:32:08] "GET /login HTTP/1.1" 200 363 PATH /login PATH /reg 127.0.0.1 - - [24/May/2018 18:32:17] "GET /reg HTTP/1.1" 200 4 127.0.0.1 - - [24/May/2018 18:32:22] "GET /regs HTTP/1.1" 200 157 PATH /regs
继续优化(web框架的使用,若要加一个时间的功能函数,只需要加在url和视图函数里边添加就可以了)
把html和图标放在templates里边
index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>Hello Luffycity!</h1> <img src="https://gss0.bdstatic.com/-4o3dSag_xI4khGkpoWK1HF6hhy/baike/w%3D268%3Bg%3D0/sign=16535fed6163f6241c5d3e05bf7f8cc5/fd039245d688d43f63d84526771ed21b0ff43bf5.jpg"> <a href="http://www.luffycity.com">路飞学城</a> </body> </html>
views.py(保存所有的视图函数和所有的逻辑处理函数的功能)
#把这些函数都放在一个py文件里边 def login(environ): #必须给它传请求接收信息,用不用得到再说 with open("templates/login.html","rb")as f: data = f.read() return data def index(environ): with open("templates/index.html","rb")as f: data = f.read() return data def favi(environ): with open("templates/favicon.ico", "rb")as f: data = f.read() return data #你们返回数据,我把数据返回到列表里 def reg(environ): with open("templates/regs.html", "rb")as f: data = f.read() return data
urls.py(分发功能)
from views import * url_patterns = [ ("/login", login), #视图函数 ("/regs", reg), ("/index", index), ("/favicon.ico",favi) ]
main.py(封装socket和整个程序的启动功能)
from wsgiref.simple_server import make_server def application(environ, start_response): #请求来了就用application来处理;所有的数据都在environ这个字典里,start_response来给我们处理格式 start_response('200 OK', [('Content-Type','text/html')]) #状态码、响应头 print("PATH", environ.get("PATH_INFO")) #当前请求路径 path = environ.get("PATH_INFO") from urls import url_patterns func = None for item in url_patterns: if path == item[0]: func = item[1] #跟上边的login匹配成功了 break if func: return [func(environ)] else: return [b'404!'] httpd = make_server('', 8080, application) #封装的socket print('Serving HTTP on port 8000.。') #开始监听HTTP请求: httpd.serve_forever()
扩展框架关于数据库的操作
models.py
#生成用户表 import pymysql #连接数据库 conn = pymysql.connect(host='127.0.0.1',port= 3306,user = 'root',passwd='',db='new_web') #db:库名 #创建游标 cur = conn.cursor() sql=''' create table userinfo( id INT PRIMARY KEY , name VARCHAR(32) , password VARCHAR(32) ) ''' cur.execute(sql) #提交 conn.commit() #关闭指针对象 cur.close() #关闭连接对象 conn.close()
然后要去在mysql里边去创建用户表,添加字段。
mysql> create database new_web; Query OK, 1 row affected (0.21 sec) mysql> use new_web; Database changed mysql> mysql> show tables; +-------------------+ | Tables_in_new_web | +-------------------+ | userinfo | +-------------------+ 1 row in set (0.17 sec) mysql> desc userinfo; +----------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +----------+-------------+------+-----+---------+-------+ | id | int(11) | NO | PRI | NULL | | | name | varchar(32) | YES | | NULL | | | password | varchar(32) | YES | | NULL | | +----------+-------------+------+-----+---------+-------+ 3 rows in set (0.04 sec) mysql> insert userinfo values(1,"kris","123"); Query OK, 1 row affected (0.24 sec) mysql> select * from userinfo; +----+------+----------+ | id | name | password | +----+------+----------+ | 1 | kris | 123 | +----+------+----------+ 1 row in set (0.00 sec)
urls.py
from views import * url_patterns = [ ("/login", login), #视图函数 ("/regs", regs), ("/index", index), ("/favicon.ico",favi), ("/timer",timer), ("/auth",auth), ]
backend.html
<body>
<h3>login successful</h3>
</body>
login.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h4>登录页面</h4> <form action="http://127.0.0.1:8080/auth" method="post"> action=必须要加好,不然不跳转哦 用户名<input type="text" name="user"> 密码<input type="password" name="pwd"> <input type="submit"> </form> </body> </html>
views.py
import pymysql
from urllib.parse import parse_qs
def timer(environ): import datetime now = datetime.datetime.now().strftime("%y-%m-%d %X") return now.encode("utf8") def auth(request): #把用户名和密码取出来 try: request_body_size = int(request.get('CONTENT_LENGTH', 0)) #拿到请求体的长度 except (ValueError): request_body_size = 0 request_body = request['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") # 连接数据库 conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='', db='new_web') # db:库名 # 创建游标 cur = conn.cursor() SQL = "select * from userinfo WHERE NAME ='%s' AND PASSWORD ='%s'" % (user, pwd) cur.execute(SQL) if cur.fetchone(): f = open("templates/backend.html", "rb") data = f.read() data = data.decode("utf8") return data.encode("utf8") else: return b"user or pwd is wrong"
web框架 功能总结
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人