自定义web框架(django)
Django基础了解知识
HTTP协议(超文本传输协议)
四大特性:
基于TCP/IP之上作用于应用层
基于请求响应
无状态 引申出cookie session token……
无连接
长连接 websocket (HTTP协议的大补丁)
数据格式:
- 请求格式
- 请求首行(请求方式,协议版本等等)
- 请求头(一大堆K:V键值对)
- \r\n 或者是\n 总之就是加一个空行
- 请求体(真正的数据 发post请求的时候才有 如果是get请求不会有)
- 响应格式
- 响应首行
- 响应头
- \r\n 或者是\n总之就是加一个空行
- 响应体(真正的数据 发post请求的时候才有 如果是get请求不会有)
- 响应状态码
- 用特定的数字表示一些意思
- 1XX:服务端已经成功接收到了你的数据 表示数据正在处理 你可以继续提交其他数据
- 2XX:服务端成功响应(200请求成功)
- 3XX:重定向(没登录淘宝,点击搜索商品,会跳转到登录页面,这就是重定向)
- 4XX:请求错误(404 请求资源不存在 403 拒绝访问)
- 5XX:服务器内部错误(500等)
- 用特定的数字表示一些意思
- 请求格式
请求方式
- get方式:朝别人要数据
- post请求:向别人提交数据(eg:用户登录)
- url:统一资源定位符
自定义web框架
主要是以下两个过程:
- 手动书写socket
- 手动处理http格式数据
## 说明
'''
我的理解是:
web框架本质就是一个基于socket的客户端和服务端进行通信,交互的过程,也就是C/S架构,其实由于是通过浏览器向服务端发送请求和响应,所以应该是B/S架构,但是浏览器(Browser)本质也是一个客户端。
如果按照一般的网络编程套路来,会报错,这是因为浏览器端走的是HTTP协议,但是服务端发过来的数据是基于TCP/UDP协议的,所以就不能识别数据而报错。
所以我们需要在发消息的时候加一个HTTP的格式标准,这样就可以在浏览器端实现正常打印, 这是由于HTTP和TCP是不同层的协议,首先传输层的是TCP,只负责传输数据,发过去就进行接收打印二进制,但是在服务端发送的是支持TCP协议的,这样在浏览器端就会报错而无法正常显示(因为浏览器支持的是HTTP协议)
'''
## 代码
import socket
server = socket.socket()
server.bind(('127.0.0.1', 8080))
server.listen(5)
"""
请求首行
b'GET /index HTTP/1.1\r\n
请求头
Host: 127.0.0.1:8080\r\n
Connection: keep-alive\r\n
Cache-Control: max-age=0\r\n
DNT: 1\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/77.0.3865.120 Safari/537.36\r\n
Sec-Fetch-Mode: navigate\r\n
Sec-Fetch-User: ?1\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
Sec-Fetch-Site: none\r\n
Accept-Encoding: gzip, deflate, br\r\n
Accept-Language: zh-CN,zh;q=0.9\r\n
\r\n
请求体
'
#请求体是空的,因为浏览器发送的是get请求,请求体只在post请求时才会有。
"""
while True:
conn, addr = server.accept()
data = conn.recv(1024)
# print(data) #打印出来的是浏览器发送过来的HTTP请求数据
conn.send(b'HTTP/1.1 200 OK\r\n\r\n')
# conn.send(b'hello')
data = data.decode('utf-8')
current_path = data.split('\r\n')[0].split(' ')[1]
# print(current_path)
if current_path == '/index': # 如果浏览器上输入的后缀是/index, 那么将.html文件读出来发送过去
# conn.send(b'index')
with open(r'index.html','rb') as f:# # 这里面用document.charset看一下网页的编码格式,不然的话可能会乱码。
conn.send(f.read())
elif current_path == '/login':
conn.send(b'login')
else:
conn.send(b'404 error')
conn.close()
类型转换
data = b'hello s11'
# 二进制转字符串
data = str(data, encoding='utf-8')
print(data,type(data))
# 字符串转二进制
data = bytes(data, encoding='utf-8')
print(data,type(data))
基于wsgiref模块
什么是wsgi
该模块实现了自定义web框架的两个过程
根据功能不同拆分成了不同的py文件
拆分完成之后 如果想要添加功,仅仅只需要在urls.py以及views.py中修改就可以了
- urls.py 路由与视图函数对象关系
- views.py 放的是视图函数 (处理业务逻辑的,函数或者类)
- templates 模板文件夹 (一堆html文件)
## 基于wsgiref.py
'''
(主要作用就是初始化服务端,然后接受浏览器端发过来的请求,把请求分门别类,传给urls找到对应的视图函数,然后在views中执行相应的视图函数并把结果返回到前端页面)
'''
from wsgiref.simple_server import make_server
from urls import urls
from views import *
def run(env,response):
"""
:param env: 请求相关的所有数据
:param response: 响应相关的所有数据
:return:
"""
response('200 OK',[])
print(env)
current_path = env.get('PATH_INFO')
# if current_path == '/index':
# # 很多业务逻辑代码
# return [b'index']
# elif current_path == '/login':
# return [b'login']
# else:
# return [b'404 error']
# 先定义一个变量名 用来存储后续匹配到的函数名
func = None
# for循环 匹配后缀
for url in urls:
if current_path == url[0]:
func = url[1] # 一旦匹配成功 就将匹配到的函数名赋值给func变量
break # 主动结束匹配
# 判断func是否有值
if func:
res = func(env)
else:
res = error(env)
return [res.encode('utf-8')]
if __name__ == '__main__':
server = make_server('127.0.0.1',8081,run)
# 实时监听该地址 只要有客户端来连接 统一交给run函数去处理
server.serve_forever() # 启动服务端
## urls.py
'''
主要作用就是用一个存有元组的列表,实现将前端接收到的后缀名与view中的函数进行对应,其实就相当于一个路由分发器,中转驿站
'''
from views import *
urls = [
('/index',index),
('/login',login),
('/xxx',xxx),
('/get_time',get_time),
('/get_user',get_user),
('/get_db',get_db),
]
# views.py
'''
用于处理业务逻辑,其实就相当于之前写的项目中的interface接口,主要根据前端接收过来的数据 然后执行相应的函数,实现相应的功能,并将结果返回给前端展现出来。
'''
def index(env):
return 'index'
def login(env):
return 'login'
def error(env):
return '404 error'
def xxx(env):
return 'xxx'
from datetime import datetime
def get_time(env):
current_time = datetime.now().strftime('%Y-%m-%d %X')
with open(r'E:\Python11\10月\1018\代码\web框架推导\templates\get_time.html','r',encoding='utf-8') as f:
data = f.read()
data = data.replace('$$time$$',current_time)
return data
from jinja2 import Template
def get_user(env):
d = {'name':'jason','pwd':'123','hobby':['read','running','music']}
with open(r'E:\Python11\10月\1018\代码\web框架推导\templates\get_user.html','r',encoding='utf-8') as f:
data = f.read()
temp = Template(data)
res = temp.render(user=d) # 将字典d传递给前端页面
# 页面上通过变量名user就能够获取到该字典
return res
import pymysql
def get_db(env):
conn = pymysql.connect(
host = '127.0.0.1',
port = 3306,
user = 'root',
password = 'root',
database = 'hupu',
charset = 'utf8',
autocommit = True
)
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
sql = "select * from user_info1"
cursor.execute(sql)
res = cursor.fetchall()
print(res)
with open(r'E:\Python11\10月\1018\代码\web框架推导\templates\get_db.html','r',encoding='utf-8') as f:
data = f.read()
temp = Template(data)
ret = temp.render(user_list = res) # 将字典d传递给前端页面 页面上通过变量名user就能够获取到该字典
return ret
### 前端代码
##get_db.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
<link href="https://cdn.bootcss.com/twitter-bootstrap/3.3.1/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.bootcss.com/twitter-bootstrap/3.3.1/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<h1 class="text-center">用户列表</h1>
<table class="table table-bordered table-striped table-hover">
<thead>
<tr>
<th>id</th>
<th>name</th>
<th>pwd</th>
</tr>
</thead>
<tbody>
{% for user_dict in user_list %}
<tr>
<td>{{ user_dict.id }}</td>
<td>{{ user_dict.name }}</td>
<td>{{ user_dict.pwd }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</body>
</html>
## get_time.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
<link href="https://cdn.bootcss.com/twitter-bootstrap/3.3.1/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.bootcss.com/twitter-bootstrap/3.3.1/js/bootstrap.min.js"></script>
</head>
<body>
$$time$$
</body>
</html>
## get_user.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
<link href="https://cdn.bootcss.com/twitter-bootstrap/3.3.1/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.bootcss.com/twitter-bootstrap/3.3.1/js/bootstrap.min.js"></script>
</head>
<body>
<p>{{ user }}</p>
<p>{{ user.name }}</p>
<p>{{ user['pwd'] }}</p>
<p>{{ user.get('hobby') }}</p>
</body>
</html>
注意1:
上面代码也实现了动静态网页的功能,那么什么是动态网页什么是静态网页呢?
静态网页:简单来说就是写死的网页,随着html代码的生成,页面的内容和显示效果就基本上不会发生变化了——除非你修改页面代码。
动态网页:页面代码虽然没有变,但是显示的内容却是可以随着时间、环境或者数据库操作的结果而发生改变的。主要体现在两种情况:1. 后端获取当前时间展示到前端;2.后端获取数据库中的数据展示到前端
注意2:
如何将后端获取的数据 传递给html页面?
后端获取的数据 传递给html页面 专用名词>>>: 模板的渲染
import jinja2就可以实现上述功能:
pip3 install jinja2
模板语法(极其贴近python后端语法)
<p>{{ user }}</p>
<p>{{ user.name }}</p>
<p>{{ user['pwd'] }}</p>
<p>{{ user.get('hobby') }}</p>
{% for user_dict in user_list %} ##在前端页面中使用后端的循环语法
<tr>
<td>{{ user_dict.id }}</td>
<td>{{ user_dict.name }}</td>
<td>{{ user_dict.pwd }}</td>
</tr>
{% endfor %}
自定义web框架(django)的更多相关文章
- web 框架的本质及自定义web框架 模板渲染jinja2 mvc 和 mtv框架 Django框架的下载安装 基于Django实现的一个简单示例
Django基础一之web框架的本质 本节目录 一 web框架的本质及自定义web框架 二 模板渲染JinJa2 三 MVC和MTV框架 四 Django的下载安装 五 基于Django实现的一个简单 ...
- day48:django前戏之HTTP协议&自定义web框架
目录 1.HTTP协议 1.HTTP协议简介 2.HTTP协议概述 3.HTTP协议工作原理 4.HTTP协议请求方法 5.HTTP协议状态码 6.URL 7.HTTP请求格式 8.HTTP响应格式 ...
- python运维开发(十七)----jQuery续(示例)web框架django
内容目录: jQuery示例 前端插件 web框架 Django框架 jQuery示例 dom事件绑定,dom绑定在form表单提交按钮地方都会绑定一个onclick事件,所有查看网站的人都能看到代码 ...
- Python 17 web框架&Django
本节内容 1.html里面的正则表达式 2.web样式简介 3.Django创建工程 Html里的正则表达式 test 用来判断字符串是否符合规定的正则 rep.test('....') ...
- Python自定义web框架、Jinja2
WSGI(Web Server Gateway Interface)是一种规范,它定义了使用python编写的web app与web server之间接口格式,实现web app与web server ...
- python web框架 django wsgi 理论
django wsgi python有个自带的wsgi模块 可以写自定义web框架 用wsgi在内部创建socket对象就可以了 自己只写处理函数就可以了django只是web框架 他也不负责写soc ...
- python web框架 django 工程 创建 目录介绍
# 创建Django工程django-admin startproject [工程名称] 默认创建django 项目都会自带这些东西 django setting 配置文件 django可以配置缓存 ...
- Web框架——Django笔记
Web框架--Django笔记 MVC和MTV MVC:Model.View.Controller MTV:Model.Template.View Django--MTV 1.创建Django程序 ...
- Python3.5学习十八 Python之Web框架 Django
Python之Web框架: 本质:Socket 引用wsgiref创建web框架 根据web框架创建过程优化所得: 分目录管理 模板单独目录 执行不同函数单独存入一个方法py文件 Web框架的两种形式 ...
随机推荐
- ionic4 ion-modal的用法
组件内部示例 <ion-header> <ion-toolbar> <ion-title>条件筛选</ion-title> <ion-button ...
- go tcp通信
----tcp 客户端 package main import ( "net" "fmt" ) func main() { conn,err := net.Di ...
- (十八)golang--defer关键字
在函数中,程序员经常需要创建资源(比如,数据库连接,文件句柄,锁等),为了在函数执行完毕后,及时释放资源,go设计者提供defer(延时机制) 用defer申明的语句不会立即执行,而是被存入到defe ...
- SAS——proc format的其他应用:invalue,picture,default,mult,prefix,noedit,_same_,_error_,other
一. proc format; invalue $test (default=200) "1"=_same_ "2"="Black" &qu ...
- svg描边路径动画
svg描边路径动画<pre><!DOCTYPE html><html> <head> <meta charset="UTF-8" ...
- Eureka配置
介绍 SpringCloud是一个完整的微服务治理框架,包括服务发现和注册,服务网关,熔断,限流,负载均衡和链路跟踪等组件. SpringCloud-Eureka主要提供服务注册和发现功能.本文提供了 ...
- 分布式应用的未来 — Distributionless
作者丨阿里云高级技术专家 至简(李云) 在技术变革推动社会发展这一时代背景下,大量支撑规模化分布式应用的技术创新.创造与创业应用而生,Could Native.Service Mesh.Serverl ...
- mvc5 源码解析1:UrlRoutingModule
注册在C:\Windows\Microsoft.NET\Framework\v2.0.50727\CONFIG \webconfig中 在该module源码中 我们可以看出注册了application ...
- UWP使用Microsoft.Data.Sqlite的记录
我在UWP中使用SQLite数据库时,并没有使用网上的SQLite for Universal App Platform方案,而使用了Microsoft和SQLite社区一起维护的Microsoft. ...
- 【UWP】实现 FindAncestor 绑定
在 WPF 里,我们是可以在 RelativeSource 上面实现的,举个例子: <Grid Tag="2"> <Button> <Grid Tag ...