Web框架的本质
所有的Web应用本质上就是一个socket服务端,而用户的浏览器就是一个socket客户端
import socket
sk = socket.socket()
sk.bind(("127.0.0.1", 80))
sk.listen()
while True:
conn, addr = sk.accept()
data = conn.recv(8096)
print(data) # 将浏览器发来的消息打印出来
conn.send(b"OK")
conn.close()
浏览器打过来的信息为:b'GET / HTTP/1.1\r\nHost: 127.0.0.1:8520\r\nConnection: keep-alive\r\nUpgrade-Insecure-Requests: 1\r\nUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 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,en-US;q=0.9,en;q=0.8,zh-CN;q=0.7\r\n\r\n'
梳理一下:
b'GET / HTTP/1.1' \
b'Host: 127.0.0.1:8520' \
b'Connection: keep-alive' \
b'Upgrade-Insecure-Requests: 1' \
b'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36' \
b'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8' \
b'Accept-Encoding: gzip, deflate, br' \
b'Accept-Language: zh,en-US;q=0.9,en;q=0.8,zh-CN;q=0.7' \
b'' \
b''
收发的消息需要按照一定的格式来,就需要了解一下HTTP协议
HTTP协议对收发消息的格式要求
每个HTTP请求和响应都遵循相同的格式,一个HTTP包含Header和Body两部分,其中Body是可选的。 HTTP响应的Header中有一个 Content-Type表明响应的内容格式。
如 text/html表示HTML网页。
"""
Web框架原理:
根据不同的URL返回不同的内容
1. 先拿到用户访问的URL是什么
2. 返回不同的内容
"""
import socket
sk = socket.socket()
sk.bind(('127.0.0.1', 8080))
sk.listen()
while 1:
conn, addr = sk.accept()
data = conn.recv(9000)
# print(data) # 用户发送的请求消息
# 从请求的消息中拿到请求的URL是什么
data_str = str(data, encoding='utf8') # 转换成字符串类型
# 按照\r\n分割字符串
list1 = data_str.split('\r\n')
url = list1[0].split()[1]
print(url)
if url == '/index/':
msg = 'This is index page!'
elif url == '/home/':
msg = 'This is home page!'
else:
msg = '404 Not Found!'
conn.send(b'HTTP/1.1 200 OK\r\n\r\n') # 先发送响应行
conn.send(bytes(msg, encoding='utf8')) # 发送响应数据
conn.close()
"""
Web框架原理:
根据不同的URL返回不同的内容函数版
1. 先拿到用户访问的URL是什么
2. 返回不同的内容
"""
import socket
sk = socket.socket()
sk.bind(('127.0.0.1', 8080))
sk.listen()
# 定义处理用户请求的函数
def index(url):
s = '你访问的是:{},这是我们的index页面'.format(url)
return bytes(s, encoding='utf8')
def home(url):
s = '你访问的主页!'
return bytes(s, encoding='utf8')
while 1:
conn, addr = sk.accept()
data = conn.recv(9000)
# print(data) # 用户发送的请求消息
# 从请求的消息中拿到请求的URL是什么
data_str = str(data, encoding='utf8') # 转换成字符串类型
# 按照\r\n分割字符串
list1 = data_str.split('\r\n')
url = list1[0].split()[1]
print(url)
if url == '/index/':
msg = index(url)
elif url == '/home/':
msg = home(url)
else:
msg = b'404 Not Found!'
conn.send(b'HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=utf-8\r\n\r\n') # 先发送响应行
conn.send(msg) # 发送响应数据
conn.close()
"""
Web框架原理:
根据不同的URL返回不同的内容函数版
1. 先拿到用户访问的URL是什么
2. 返回不同的内容
"""
import socket
sk = socket.socket()
sk.bind(('127.0.0.1', 8080))
sk.listen()
# 定义处理用户请求的函数
def index(url):
s = '你访问的是:{},这是我们的index页面'.format(url)
return bytes(s, encoding='utf8')
def home(url):
s = '你访问的主页!'
return bytes(s, encoding='utf8')
def dsb(url):
return bytes('夏雨豪是个什么人!', encoding='utf8')
# 定义一个用户访问的URL和我将要执行的函数的对应关系
url_func = [
('/index/', index),
('/home/', home),
('/xyh/', dsb),
]
while 1:
conn, addr = sk.accept()
data = conn.recv(9000)
# print(data) # 用户发送的请求消息
# 从请求的消息中拿到请求的URL是什么
data_str = str(data, encoding='utf8') # 转换成字符串类型
# 按照\r\n分割字符串
list1 = data_str.split('\r\n')
url = list1[0].split()[1]
print(url)
func = None
for i in url_func:
if i[0] == url:
func = i[1]
break
if func:
msg = func(url)
else:
msg = b'404 Not Found!'
conn.send(b'HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=utf-8\r\n\r\n') # 先发送响应行
conn.send(msg) # 发送响应数据
conn.close()
"""
Web框架原理:
返回具体的HTML页面
"""
import socket
sk = socket.socket()
sk.bind(('127.0.0.1', 8080))
sk.listen()
# 定义处理用户请求的函数
def index(url):
s = '你访问的是:{},这是我们的index页面'.format(url)
return bytes(s, encoding='utf8')
def home(url):
s = '你访问的主页!'
return bytes(s, encoding='utf8')
def dsb(url):
return bytes('小明是个什么人!', encoding='utf8')
def login(url):
# 返回login.html
with open('login.html', 'rb') as f:
return f.read()
# 定义一个用户访问的URL和我将要执行的函数的对应关系
url_func = [
('/index/', index),
('/home/', home),
('/xyh/', dsb),
('/login/', login),
]
while 1:
conn, addr = sk.accept()
data = conn.recv(9000)
# print(data) # 用户发送的请求消息
# 从请求的消息中拿到请求的URL是什么
data_str = str(data, encoding='utf8') # 转换成字符串类型
# 按照\r\n分割字符串
list1 = data_str.split('\r\n')
url = list1[0].split()[1]
print(url)
func = None
for i in url_func:
if i[0] == url:
func = i[1]
break
if func:
msg = func(url)
else:
msg = b'404 Not Found!'
conn.send(b'HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=utf-8\r\n\r\n') # 先发送响应行
conn.send(msg) # 发送响应数据
conn.close()
"""
Web框架原理:
返回具体的HTML页面
"""
import time
import socket
sk = socket.socket()
sk.bind(('127.0.0.1', 8080))
sk.listen()
# 定义处理用户请求的函数
def index(url):
with open('index.html', 'r', encoding='utf8') as f1:
html_s = f1.read()
# 根据用户不同,取出不同的数据
# 用不同的数据去替换页面上的特殊符号
now = str(time.time())
msg = html_s.replace('@@xx@@', now)
return bytes(msg, encoding='utf8')
def home(url):
s = '你访问的主页!'
return bytes(s, encoding='utf8')
def dsb(url):
return bytes('小明是个什么人!', encoding='utf8')
def login(url):
# 返回login.html
with open('login.html', 'rb') as f:
return f.read()
# 定义一个用户访问的URL和我将要执行的函数的对应关系
url_func = [
('/index/', index),
('/home/', home),
('/xyh/', dsb),
('/login/', login),
]
while 1:
conn, addr = sk.accept()
data = conn.recv(9000)
# print(data) # 用户发送的请求消息
# 从请求的消息中拿到请求的URL是什么
data_str = str(data, encoding='utf8') # 转换成字符串类型
# 按照\r\n分割字符串
list1 = data_str.split('\r\n')
url = list1[0].split()[1]
print(url)
func = None
for i in url_func:
if i[0] == url:
func = i[1]
break
if func:
msg = func(url)
else:
msg = b'404 Not Found!'
conn.send(b'HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=utf-8\r\n\r\n') # 先发送响应行
conn.send(msg) # 发送响应数据
conn.close()
"""
Web框架原理:
返回具体的HTML页面
"""
import time
from wsgiref.simple_server import make_server
# 定义处理用户请求的函数
def index(url):
with open('index.html', 'r', encoding='utf8') as f1:
html_s = f1.read()
# 根据用户不同,取出不同的数据
# 用不同的数据去替换页面上的特殊符号
now = str(time.time())
msg = html_s.replace('@@xx@@', now)
return bytes(msg, encoding='utf8')
def home(url):
s = '你访问的主页!'
return bytes(s, encoding='utf8')
def dsb(url):
return bytes('小明是个什么人!', encoding='utf8')
def login(url):
# 返回login.html
with open('login.html', 'rb') as f:
return f.read()
# 定义一个用户访问的URL和我将要执行的函数的对应关系
url_func = [
('/index/', index),
('/home/', home),
('/xyh/', dsb),
('/login/', login),
]
# wsgiref模块的格式要求
def run_server(environ, start_response):
start_response('200 OK', [('Content-Type', 'text/html;charset=utf8'), ]) # 设置HTTP响应的状态码和头信息
url = environ['PATH_INFO'] # 取到用户输入的url
func = None
for i in url_func:
if i[0] == url:
func = i[1]
break
if func:
msg = func(url)
else:
msg = b'404 Not Found!'
return [msg, ]
if __name__ == '__main__':
httpd = make_server('127.0.0.1', 8080, run_server)
print("我在8080等你哦...")
httpd.serve_forever()
"""
Web框架原理:
返回具体的HTML页面
"""
import time
from wsgiref.simple_server import make_server
# 定义处理用户请求的函数
def index(url):
with open('index.html', 'r', encoding='utf8') as f1:
html_s = f1.read()
# 根据用户不同,取出不同的数据
# 用不同的数据去替换页面上的特殊符号
now = str(time.time())
msg = html_s.replace('@@xx@@', now)
return bytes(msg, encoding='utf8')
def home(url):
s = '你访问的主页!'
return bytes(s, encoding='utf8')
def dsb(url):
return bytes('小明是个什么人!', encoding='utf8')
def login(url):
# 返回login.html
with open('login.html', 'rb') as f:
return f.read()
# 定义一个用户访问的URL和我将要执行的函数的对应关系
url_func = [
('/index/', index),
('/home/', home),
('/xyh/', dsb),
('/login/', login),
]
# wsgiref模块的格式要求
def run_server(environ, start_response):
start_response('200 OK', [('Content-Type', 'text/html;charset=utf8'), ]) # 设置HTTP响应的状态码和头信息
url = environ['PATH_INFO'] # 取到用户输入的url
func = None
for i in url_func:
if i[0] == url:
func = i[1]
break
if func:
msg = func(url)
else:
msg = b'404 Not Found!'
return [msg, ]
if __name__ == '__main__':
httpd = make_server('127.0.0.1', 8080, run_server)
print("我在8080等你哦...")
httpd.serve_forever()
对于真实开发中的python web程序来说,一般会分为两部分:服务器程序和应用程序。
服务器程序负责对socket服务器进行封装,并在请求到来时,对请求的各种数据进行整理。
应用程序则负责具体的逻辑处理。
为了方便应用程序的开发,就出现了众多的Web框架,例如:Django、Flask、web.py 等。
WSGI(Web Server Gateway Interface)就是一种规范,它定义了使用Python编写的web应用程序与web服务器程序之间的接口格式,实现web应用程序与web服务器程序间的解耦。
常用的WSGI服务器有uwsgi、Gunicorn。而Python标准库提供的独立WSGI服务器叫wsgiref,Django开发环境用的就是这个模块来做服务器。
利用wsgiref模块来替换我们自己写的web框架的socket server。
模板的原理就是字符串替换,我们只要在HTML页面中遵循jinja2的语法规则写上,其内部就会按照指定的语法进行相应的替换,从而达到动态的返回内容。
Python中Web框架的分类
收发socket消息
根据不同的URL执行不同的函数(业务逻辑)
字符串替换(动态网页)
第一种分类:(按照上面的三部分功能划分)
自己实现b和c,使用第三方的a --> Django
自己实现b,使用第三方的a和c --> Flask
自己实现a、b、c --> Tornado
第二种分类:
Django(大而全)
其他
Django
安装
命令行安装:
pip install django==1.11.16
补充:
pip install django==1.11.16 -i
https://pypi.tuna.tsinghua.edu.cn/simple some-package
pip list
PyCharm安装
创建我们第一个Django项目
命令行创建
django-admin startproject 项目名
PyCharm创建
File -> new project -> 左边选第二项,右边填项目名并且选择Python解释器
运行Django项目
命令行
切换到项目的目录下
python manage.py runserver
python manage.py runserver 127.0.0.1:8080
python manage.py runserver 8090
PyCharm
点绿色的三角(注意左侧名称要与项目名相同)
TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(BASE_DIR, "template")], # template文件夹位置 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }, ] <!--用来存放HTML页面-->
STATIC_URL = '/static/' # HTML中使用的静态文件夹前缀
STATICFILES_DIRS = [
os.path.join(BASE_DIR, "static"), # 静态文件存放位置
]
css,js样式等
HttpResponse
内部传入一个字符串参数,返回给浏览器。
def index(request):
# 业务逻辑代码
return HttpResponse("OK")
render
找到那个html文件 读取文件内容 按照HTTP协议的格式返回
redirect
接受一个URL参数,表示跳转到指定的URL。
def index(request):
# 业务逻辑代码
return redirect("/home/")

清风深知杨柳意,啤酒龙虾难相聚。

浙公网安备 33010602011771号