纯手撸Django框架
https协议:
四大特性:
1.HTTP是一个基于TCP/IP通信协议来传递数据(HTML 文件, 图片文件, 查询结果等)。
2.基于请求响应
3.HTTP是无状态:HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。
4.HTTP是无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。
数据格式
请求:
请求首行GET url HTTP/1.1
请求头(一大堆k,v的键值对组成)
\r\n
请求体
响应:
同上
响应状态码
1XX:服务器已接收到你的数据正在处理,你可以继续提交数据
2XX:请求成功,返回相应数据
3XX:重定向
4XX:请求不存在(404)
5XX:服务器错误
基于socket写一个web应用
import socket
"""
请求首行
b'GET / HTTP/1.1\r\n
请求头(一大堆kv键值对)
Host: 127.0.0.1:8080\r\n
Connection: keep-alive\r\n
Upgrade-Insecure-Requests: 1\r\n
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36\r\n
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3\r\n
Accept-Encoding: gzip, deflate, br\r\n
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8\r\n
\r\n
请求体
"""
server = socket.socket() # 不传参数默认就是TCP协议
server.bind(('127.0.0.1',8080))
server.listen(5)
while True:
conn, addr = server.accept() # 阻塞 等待客户端链接
data = conn.recv(1024)
conn.send(b'HTTP/1.1 200 OK\r\n\r\n')
print(data)
# 手动处理http数据获取用户访问的路径
current_path = data.decode('utf-8').split('\r\n')[0].split(' ')[1]
if current_path == '/index':
# 路由匹配上之后返回index
# conn.send(b'<h1>index</h1>')
with open('index.html','rb') as f:
conn.send(f.read())
else:
# 当匹配不上的时候统一返回404
conn.send(b'404')
conn.close()
利用 wsgiref 和 jinja2 模块手撸Django框架
from wsgiref.simple_server import make_server
from urls import *
def run(env,response):
"""
:param env: 请求相关的信息
:param response: 响应相关的信息
:return:
"""
print(env) # 是一个大字典 里面装了一堆处理好了的键值对数据
response('200 OK',[('username','jason'),('password','123')]) # 固定写法 后面列表里面一个个元祖会以响应头kv键值对的形式返回给客户端
# 获取用户访问的路径
current_path = env.get('PATH_INFO')
# if current_path == '/index':
# return [b'index']
# elif current_path == '/login':
# return [b'login']
# 定义一个存储函数名的变量名
func = None
# 循环比对路由与试图函数的映射关系
for url_map in urls: # url_map = ('/index',index)
if current_path == url_map[0]:
func = url_map[1]
# 只要匹配成功 直接结束循环
break
if func:
res = func(env)
else:
res = error(env)
return [res.encode('utf-8')]
if __name__ == '__main__':
server = make_server('127.0.0.1',8080,run)
server.serve_forever()
urls.py
from views import *
urls = [
('/index',index),
('/login',login),
('/reg',reg),
('/get_time',get_time),
('/get_user',get_user),
('/get_db',get_db),
]
view.py
import time
from jinja2 import Template
import pymysql
def index(env):
return 'index'
def login(env):
return 'login'
def reg(env):
return 'reg'
def get_time(env):
# 先获取当前时间
current_time = time.strftime('%Y-%m-%d %X')
# 打开html文件读取内容返回给客户端
with open(r'templates/get_time.html','r',encoding='utf-8') as f:
data = f.read()
# 因为是以r模式打开的文件,所有获取到的内容就是一堆字符串
res = data.replace('@@time@@',current_time) # 字符串的替换
return res
def get_user(env):
with open(r'templates/get_user.html','r',encoding='utf-8') as f:
data = f.read()
tmp = Template(data)
# 将字典传递给前端页面 前端通过变量名user_dic就可以获取到该字典
return tmp.render(user_dic={'name':"jason",'password':'123'})
def get_db(env):
# 连接数据库 获取数据 渲染到前端页面
conn = pymysql.connect(
host = '127.0.0.1',
port = 3306,
user = 'root',
password = '123',
database = 'day54',
charset = 'utf8',
autocommit = True
)
cursor = conn.cursor(pymysql.cursors.DictCursor)
cursor.execute('select * from userinfo')
user_dict= cursor.fetchall() # [{},{},{},{}]
with open(r'templates/get_db.html','r',encoding='utf-8') as f:
data = f.read()
tmp = Template(data)
return tmp.render(user_dict=user_dict)
def error(env):
return '404 error'
? 模板语法
{{}} 变量相关
{%%} 逻辑相关
{{ data }}
{{ data.name }}
{{ data['name'] }}
{{ data.get('name') }}
{% for user_dict in user_list%} [{},{},{}]
{{ user_dict }}
{% endfor %}
原文:https://www.cnblogs.com/ZKPython/p/10981762.html