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. E - Petya and Exam CodeForces - 832B 字典树+搜索

    E - Petya and Exam CodeForces - 832B 这个题目其实可以不用字典树写,但是因为之前写过poj的一个题目,意思和这个差不多,所以就用字典树写了一遍. 代码还是很好理解的 ...

  2. tp5中提示错误A non well formed numeric value encountered

    问题因为自动完成时间导致的 原来我的数据库是这样的 修改成下面这样就好了

  3. CSS中的间距设置与盒子模型

    CSS间距 内补白 外补白 盒子模型 CSS间距 很多时候我们为了美观,需要对内容进行留白设置,这时候就需要设置间距了. 内补白 设置元素的内间距 padding: 检索或设置对象四边的内部边距 pa ...

  4. 【MySQL基础总结】索引的使用

    索引的使用 概述 1.索引由数据库中一列或多列组合而成,其作用是提高对表中数据的查询速度 2.索引的优点是可以提高检索数据的速度 3.缺点是创建和维护索引需要耗费时间 4.所以索引可以提高查询速度,减 ...

  5. 深度剖析西门子PLC的开放式TCP通信

    对于自控或电气工程师来说,西门子PLC是每个人都非常熟悉的一款PLC品牌:而对于上位机开发工程师来说,Socket通信或TCP/IP协议也是必须要掌握的一种通信方式.刚好手头有一款西门子的200Sma ...

  6. [hdu5418 Victor and World]floyd + 状压DP 或 SPFA

    题意:给n个点,m条边,每次只能沿边走,花费为边权值,求从1出发经过所有其它点≥1次最后回到1的最小花费. 思路: 状压DP.先用Floyd得到任意两点间的最短距离,转移时沿两个点的最短路转移.此时的 ...

  7. SpringData表关系:多对多

    一.编写实体类配置关联关系: 1.多对多使用注解@ManyToMany配置:a. 在实体中添加一个集合属性 b.在属性上添加ManyToMany注解 c.@JoinTable 注解配置关联关系(nam ...

  8. python实现摇骰子猜大小函数升级没把加注及三大运行商短信验证过滤

    摇骰子游戏升级 此次更改增加下注功能,启动资金1000元,每次赔率都是一倍,钱输光退出. 源码: #!/user/bin/env python #-*-coding:utf-8 -*- #Author ...

  9. Redux:异步操作

    最近状态不太好,学习redux的异步操作花的时间比想象的多,这里尽量清晰简要的表述一下在redux中怎么实现异步操作. 先回顾一下同步操作: 我们用redux执行同步的时候,都是先发起一个dispat ...

  10. vue-cli项目上传到github预览问题

    上传前先npm run build 后git push origin master 问题:chunk无法加载? 原因:在github.io请求chunk时,chunk的url使用的是publicPat ...