PythonWeb框架的本质

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

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

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

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

构建一个html页面返回
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1"> <style>
div{
background-color: #7fb8f7;
color: red;
}
</style>
</head> <body>
<div>你好,世界</div>
</body>
</html>

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

服务端

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

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

GET / HTTP/1.1
Host: 127.0.0.1:8002
Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.162 Safari/537.36
Sec-Fetch-Dest: document
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
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
http协议工作原理

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

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

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

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

# 1xx消息——请求已被服务器接收,继续处理
# 2xx成功——请求已成功被服务器接收、理解、并接受
# 3xx重定向——需要后续操作才能完成这一请求
# 4xx请求错误——请求含有词法错误或者无法被执行
# 5xx服务器错误——服务器在处理某个正确请求时发生错误

构建Web框架

简单版Web框架

test1.html

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<style>
div {
background-color: #7fb8ff;
font-size: 16px;
}
</style>
</head> <body>
<div>欢迎访问xx商城</div> <ul>
<li>aa</li>
<li>bb</li>
<li>cc</li>
</ul> </body>
</html>

test1.py

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

html

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="test2.css">
<link rel="icon" href="2.jpg">
</head>
<body>
<div>欢迎访问和软商城</div> <ul>
<li>aa</li>
<li>bb</li>
<li>cc</li>
</ul>
<img src="2.jpg" alt="美女">
<script src="test2.js"></script>
</body>
</html>

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

test2.css

div {
background-color: #7fb8ff;
font-size: 16px;
}

test2.js

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

test2.py

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

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

test3.html

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

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="test2.css">
<link rel="icon" href="2.jpg">
</head>
<body>
<div>欢迎访问和软商城</div> <ul>
<li>aa</li>
<li>bb</li>
<li>cc</li>
</ul>
<img src="2.jpg" alt="美女">
<script src="test2.js"></script>
</body>
</html>

test3.py

import socket

server = socket.socket()
server.bind(('127.0.0.1', 8001))
server.listen() def html(conn):
with open('test3.html', mode='rb') as f1:
conn.send(f1.read())
conn.close() def css(conn):
with open('test2.css', mode='rb') as f1:
conn.send(f1.read())
conn.close() def jpg(conn):
with open('2.jpg', mode='rb') as f1:
conn.send(f1.read())
conn.close() def js(conn):
with open('test2.js', mode='rb') as f1:
conn.send(f1.read())
conn.close() request_list = [
('/', html),
('/test2.css', css),
('/2.jpg', jpg),
('/test2.js', js),
] while 1:
conn, addr = server.accept()
client_data = conn.recv(1024)
request_path = client_data.decode('utf-8').split('\r\n')[0].split()[1]
# 服务端与客户端建立联系必须要遵循一个协议,此时我们用http协议示例。
conn.send('HTTP/1.1 200 OK \r\nk1:v1\r\n\r\n'.encode('utf-8'))
for i in request_list:
if request_path == i[0]:
i[1](conn)
conn.close()

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

并发版Web框架

test4.html

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="test2.css">
<link rel="icon" href="2.jpg">
</head>
<body>
<div>欢迎访问和软商城</div> <ul>
<li>aa</li>
<li>bb</li>
<li>cc</li>
</ul>
<img src="2.jpg" alt="美女">
<script src="test2.js"></script>
</body>
</html>

test4.py

import socket
from threading import Thread server = socket.socket()
server.bind(('127.0.0.1', 8001))
server.listen() def html(conn):
with open('test3.html', mode='rb') as f1:
conn.send(f1.read())
conn.close() def css(conn):
with open('test2.css', mode='rb') as f1:
conn.send(f1.read())
conn.close() def jpg(conn):
with open('2.jpg', mode='rb') as f1:
conn.send(f1.read())
conn.close() def js(conn):
with open('test2.js', mode='rb') as f1:
conn.send(f1.read())
conn.close() request_list = [
('/', html),
('/test2.css', css),
('/2.jpg', jpg),
('/test2.js', js),
] while 1:
conn, addr = server.accept()
client_data = conn.recv(1024)
request_path = client_data.decode('utf-8').split('\r\n')[0].split()[1]
print(request_path)
# 服务端与客户端建立联系必须要遵循一个协议,此时我们用http协议示例。
conn.send('HTTP/1.1 200 OK \r\nk1:v1\r\n\r\n'.encode('utf-8'))
for i in request_list:
if request_path == i[0]:
t = Thread(target=i[1],args=(conn,))
t.start()
# conn.close()
动态版Web框架

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

test5.html

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="test2.css">
<link rel="icon" href="2.jpg">
</head>
<body>
<div>欢迎访问和软商城</div> <ul>
<li>aa</li>
<li>bb</li>
<li>cc</li>
</ul>
<img src="2.jpg" alt="美女">
<script src="test2.js"></script>
</body>
</html>

test5.py

import socket
from threading import Thread
import time server = socket.socket()
server.bind(('127.0.0.1', 8001))
server.listen() def html(conn):
time_now = time.strftime('%Y/%m/%d %H:%M:%S',time.localtime())
with open('test5.html',encoding='utf-8') as f1:
data = f1.read().format(time_now=time_now)
conn.send(data.encode('utf-8'))
conn.close() def css(conn):
with open('test2.css', mode='rb') as f1:
conn.send(f1.read())
conn.close() def jpg(conn):
with open('2.jpg', mode='rb') as f1:
conn.send(f1.read())
conn.close() def js(conn):
with open('test2.js', mode='rb') as f1:
conn.send(f1.read())
conn.close() request_list = [
('/', html),
('/test2.css', css),
('/2.jpg', jpg),
('/test2.js', js),
] while 1:
conn, addr = server.accept()
client_data = conn.recv(1024)
request_path = client_data.decode('utf-8').split('\r\n')[0].split()[1]
print(request_path)
# 服务端与客户端建立联系必须要遵循一个协议,此时我们用http协议示例。
conn.send('HTTP/1.1 200 OK \r\nk1:v1\r\n\r\n'.encode('utf-8'))
for i in request_list:
if request_path == i[0]:
t = Thread(target=i[1],args=(conn,))
t.start()
# 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的简单用法:

from wsgiref.simple_server import make_server

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

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

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

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

my.cnf

[root@mysql-test ~]# cat /etc/my.cnf
[mysql]
default-character-set=utf8 [mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
symbolic-links=0 character-set-server=utf8
default-storage-engine=INNODB max_connections=200
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid [client]
password = ZHOUjian.24
user = root

socket服务端

from wsgiref.simple_server import make_server

import time

def html(conn):
time_now = time.strftime('%Y/%m/%d %H:%M:%S', time.localtime())
with open('test5.html', encoding='utf-8') as f1:
data = f1.read().format(time_now=time_now)
conn.send(data.encode('utf-8'))
conn.close() def css(conn):
with open('test2.css', mode='rb') as f1:
data = f1.read()
return data def jpg(conn):
with open('2.jpg', mode='rb') as f1:
data = f1.read()
return data def js(conn):
with open('test2.js', mode='rb') as f1:
data = f1.read()
return data request_list = [
('/', html),
('/test2.css', css),
('/2.jpg', jpg),
('/test2.js', js),
] def application(environ, start_response):
start_response('200 OK', [('k1', 'v1'), ('k2', 'v2')])
print(environ)
request_path = environ['PATH_INFO']
for i in request_list:
if request_path == i[0]:
ret = i[1]()
return [ret]
else: return [b'<h1>404.....</h1>'] httpd = make_server('127.0.0.1', 8080, application)
print('Serving HTTP on port 8080...')
# 开始监听HTTP请求:
httpd.serve_forever()

pymysql1.py(创建数据)

import pymysql

conn = pymysql.connect("121.36.43.223", "admin", "ZHOUjian.21")

cursor = conn.cursor(pymysql.cursors.DictCursor)

# 创建 webtest数据库
cursor.execute('create database webtest;') # 创建userinfo数据库表
cursor.execute('create table webtest.userinfo(id int,name varchar(20),age int);') cursor.execute("""
insert into webtest.userinfo(id,name,age) values
(1,'幽梦',18),
(2,'flying',19),
(3,'渐渐',20);
"""
) conn.commit()
cursor.close()
conn.close()

pymysql2.py(getdata)

import pymysql

def get_data():
conn = pymysql.connect("121.36.43.223", "admin", "ZHOUjian.21")
cursor = conn.cursor(pymysql.cursors.DictCursor)
cursor.execute("select * from webtest.userinfo;")
data = cursor.fetchone()
conn.commit()
cursor.close()
conn.close()
return data
wsgiref模块版+数据库+jinja2 web框架

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

下载

pip install jinja2

getdata

import pymysql

def get_data():
conn = pymysql.connect("121.36.43.223", "admin", "ZHOUjian.21")
cursor = conn.cursor(pymysql.cursors.DictCursor)
cursor.execute("select * from webtest.userinfo;")
data = cursor.fetchone()
conn.commit()
cursor.close()
conn.close()
return data

test7.html

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="test2.css">
<link rel="icon" href="2.jpg">
</head>
<body>
<div>欢迎访问和软商城</div>
<div>{time_now}</div>
<ul>
<li>aa</li>
<li>bb</li>
<li>cc</li>
</ul>
<img src="2.jpg" alt="美女">
<script src="test2.js"></script>
</body>
</html>

socket服务端

from threading import Thread
from wsgiref.simple_server import make_server
from Day15.pymysql2 import showdata
from jinja2 import Template def html(conn):
userinfo_data = showdata()
print(userinfo_data)
with open('test7.html', 'rb',encoding='utf-8') as f1:
data = f1.read()
temp = Template(data)
print(temp)
data = temp.reader({'userinfo':userinfo_data})
data = data.encode('utf-8')
return data def css(conn):
with open('test2.css','rb') as f1:
data = f1.read()
return data def jpg(conn):
with open('2.jpg','rb') as f1:
data = f1.read()
return data def js(conn):
with open('test2.js','rb') as f1:
data = f1.read()
return data urlpatterns = [
('/', html),
('/test2.css', css),
('/2.jpg', jpg),
('/test2.js', js),
] def application(environ, start_response):
# print(environ)
# conn.send(b'HTTP/1.1 200 ok\r\n\r\nxxxx')
start_response('200 OK', [('k1','v1'),('k2','v2')])
# print(environ['PATH_INFO'])
path = environ['PATH_INFO'] for i in urlpatterns:
if path == i[0]:
ret = i[1]()
break
else:
ret = b'404 not found!!!!'
return [ret] httpd = make_server('127.0.0.1', 8080, application) print('Serving HTTP on port 8080...')
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. 第三章:Python高级编程-深入类和对象

    第三章:Python高级编程-深入类和对象 Python3高级核心技术97讲 笔记 3.1 鸭子类型和多态 """ 当看到一直鸟走起来像鸭子.游泳起来像鸭子.叫起来像鸭子 ...

  2. 数据结构--队列(Java实现)

    数据结构--队列(Java实现) 博客说明 文章所涉及的资料来自互联网整理和个人总结,意在于个人学习和经验汇总,如有什么地方侵权,请联系本人删除,谢谢! 简介 队列是一种特殊的线性表,特殊之处在于它只 ...

  3. SpringBoot:整合Druid、MyBatis

    目录 简介 JDBC 导入依赖 连接数据库 CRUD操作 自定义数据源 DruidDataSource Druid 简介 配置数据源 配置 Druid 数据源监控 配置 Druid web 监控 fi ...

  4. SpringBoot:模板引擎 thymeleaf、ContentNegotiatingViewResolver、格式化转换器

    目录 模板引擎 thymeleaf ContentNegotiatingViewResolver 格式化转换器 模板引擎 thymeleaf.ContentNegotiatingViewResolve ...

  5. js和jq的获取焦点失去焦点写法

  6. 2020年python开发微信小程序,公众号,手机购物商城APP

    2020年最新的技术全栈,手机短信注册登陆等运用, 精准定位用户 支付宝支付 以及前后端从0到大神的全部精解 2020年最新的技术全栈,手机短信注册登陆等运用, 精准定位用户 支付宝支付 以及前后端从 ...

  7. 【Spark】一起了解一下大数据必不可少的Spark吧!

    目录 Spark概述 官网 Spark是什么? 特点 Spark架构模块 主要架构模块 Spark Core Spark SQL Spark Streaming MLlib GraghX 集群管理器 ...

  8. 【Linux基础总结】Linux基本环境

    Linux基本环境 对Linux的基础认识 虚拟机进入终端: [root@hadoop-senior Desktop] # 用户名 主机名 所在目录名称 #:表示当前用户属于root用户,超级管理员用 ...

  9. Struts2-Tiles 2.5.2 升级指南和通配符拓展

    最近工程从Struts2.3.18升级Struts2.5.2导致相关联的插件都需要升级到相同版本,其中tiles的变化最大. 1.web.xml上 listener org.apache.struts ...

  10. ReactNative报错:Can't find variable: __fbBatchedBridge

    最近开始研究ReactNative,首先根据网上教程 http://www.codeceo.com/article/windows-react-native-android.html 一步一步来.完成 ...