python Django之Web框架本质 (2)
文章目录
一.Web应用本质
1.socket本质
二.发送HTTP协议、响应
1.HTTP协议
2.HTTP发送响应
◼ 静态网页
◼ 动态网页
三.jinja2模板渲染
一.Web应用本质
为了了解Django的客户端与服务端的交互原理,我们需要了解Web应用的本质方便以后更加的理解Django原理
在Web应用中,服务器把网页传给浏览器,实际上就是把网页的HTML代码发送给浏览器,让浏览器显示出来。而浏览器和服务器之间的传输协议是HTTP。所以本质上就是:
浏览器发送一个HTTP请求
服务器收到请求,生成一个HTML文档
服务器把HTML文档作为HTTP响应的Body发送给浏览器
浏览器收到HTTP响应,从HTTP Body取出HTML文档并显示。
而在http协议中,我们可以用socket来实现
1.socket本质
web服务器本质上可以认为是一段代码,可以不断的处理http协议的网络请求,而http协议可以使用socket实现,并且http协议是一个无状态的协议,即浏览器发起请求,服务器接收请求,然后给浏览器回复数据,然后断开连接;那么可以用socket来实现一个最简单的web服务器。
HTTP:
无状态、短连接
TCP:
不断开(socket连接)
服务器把HTML文档作为HTTP响应的Body发送给浏览器
WEB应用(网站)
浏览器(socket客服端)
在客户端访问网址后,通过ping 网址 转化为ip地址进行访问(默认监听80端口)
浏览器(socket服务端)
- 监听ip和端口
- 收到客户端传来的数据
- 响应客户端,发送响应数据
- 断开客户端连接
示意如下:
import socket
sock = socket.socket()
网页和监听端口(这里先默认本机端口的8080)
sock.bind((‘127.0.0.1’,8080))
等待五个用户
sock.listen(5)
因为socket是TCP协议不断开
while True:
#等待
conn,addr= sock.accept()
# 有人来连接
# 获取用户发送的数据
data = conn.recv(8096)
# 回数据,转字节
conn.send(b’123123’)
# 断开客户端连接
conn.close()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
访问127.0.0.1:8080
示意如下:
在这里插入图片描述
二.发送HTTP协议、响应
1.HTTP协议
在html中发送获取数据都遵从着HTTP协议,随着时间的变化一点一点的在改变,直到现在,我们可以通过socket发来的请求打印data来查看http发送的响应数据:
print(data)
#返回
“”"
响应头
状态:200 OK
‘GET /(get请求数据默认放这) HTTP/1.1’
‘Host: 127.0.0.1:8080’
‘User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:84.0) Gecko/20100101 Firefox/84.0’
‘Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,/;q=0.8’
‘Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2’
‘Accept-Encoding: gzip, deflate’
‘Connection: keep-alive’
‘Upgrade-Insecure-Requests: 1’
请求体:如果是post请求数据放这
响应体
‘GET /favicon.ico HTTP/1.1’
‘Host: 127.0.0.1:8080’
‘User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:84.0) Gecko/20100101 Firefox/84.0’
‘Accept: image/webp,/’
‘Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2’
‘Accept-Encoding: gzip, deflate’
‘Connection: keep-alive’
‘Referer: http://127.0.0.1:8080/’
“”"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
很显然我们上面写的代码没有根据HTTP的协议发送请求,应该遵循HTTP协议,用户在页面上看到的内容”字符串“(看到页面效果,是由浏览器解析出来的)
示意如下:
import socket
sock = socket.socket()
网页和监听端口(这里先默认本机端口的8080)
sock.bind((‘127.0.0.1’,8080))
等待五个用户
sock.listen(5)
因为socket是TCP协议不断开
while True:
#等待
conn,addr= sock.accept()
# 有人来连接
#1. 获取用户发送的数据
data = conn.recv(8096)
# 4. 遵循http协议
conn.send(b'HTTP/1.1 200 OK\r\n\r\n')
# 5. 返回数据,转字节
conn.send(b'123123')
# 6. 断开客户端连接
conn.close()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2.HTTP发送响应
但是我们目前怎么样都只有一个页面,不能像其他的网站一样有多个页面,所以我们要从客户端发来的请求中拿到数据在做出响应在返回:
获取用户发送的数据
接收请求传来的数据
分割数据
遵循http协议
返回相应数据,转字节
断开客户端连接
示意如下:
import socket
相应数据函数
def f1(request):
return b"f1"
def f2(request):
return b"f2"
类似django的路由
routers = [
(’/xxx’, f1),
(’/ooo’, f2),
]
主函数
def run():
sock = socket.socket()
# 网页和监听端口(这里先默认本机端口的8080)
sock.bind((‘127.0.0.1’, 8080))
# 等待五个用户
sock.listen(5)
# 因为socket是TCP协议不断开
while True:
# 等待
conn, addr = sock.accept()
# 有人来连接
# 1. 获取用户发送的数据
data = conn.recv(8096)
# 2. 接收请求传来的数据
data = str(data, encoding=‘utf-8’)
# 3. 分割数据,请求头,和请求体
headers, bodys = data.split(’\r\n\r\n’)
temp_list = headers.split(’\r\n’)
# 获取一.get请求 二.访问url 三.请求体
res, url, hea = temp_list[0].split(’ ‘)
func_name = None
# 4. 遵循http协议
conn.send(b’HTTP/1.1 200 OK\r\n\r\n’)
# 这时候打印的就是后缀的值
print(url)
# 遍历路由
for item in routers:
if item[0] == url:
# 判断是否是该url返回函数地址
func_name = item[1]
break
# 判断函数是否存在
if func_name:
response = func_name(data)
else:
response = b"404 not found"
# 5. 返回相应数据,转字节conn.send(response)# 6. 断开客户端连接conn.close()
if name == ‘main’:
run()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
访问127.0.0.1:8080
示意如下:
在这里插入图片描述
所以通过上面例子我们可以写一个html然后渲染。
◼ 静态网页
因为如果想要数据库实时动态产生,我们需要数据库的帮助,不过在开始介绍前,我们先写静态网页,首先在当前主目录下创建两个文件夹动态网页和静态网页。用于区分一下动态网页和静态网页。
在静态文件/index.html中定义视图如下:
ID | 用户名 | 邮箱 |
---|---|---|
1 | root | root@qq.com |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 在f1中定义函数如下:
def f1(request)
f=open(‘静态网页/index.html’, ‘rb’)
data=f.read()
f.close()
return data
1
2
3
4
5
访问127.0.0.1:8080/xxx
示意如下:
在这里插入图片描述
◼ 动态网页
在前面的文章有写到操作数据库的方法,种类很多这里我们使用pymysql来实现,如果没看到这里的可以点开链接:点我!!!进行查看。
导入驱动程序
pip install pymysql
1
创建数据库连接
import pymysql
创建连接
conn = pymysql.connect(host=‘127.0.0.1’, port=3306, user=‘root’, passwd=‘xxx’, db=‘myemployees’)
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
关闭
cursor.close()
conn.close()
1
2
3
4
5
6
7
在这里我们把/ooo改成/userlist.htm为了告诉大家django的路由和这个很像
routers = [
(’/xxx’, f1),
(’/userlist.htm’, f2),
]
1
2
3
4
在动态网页/userlist.html中定义视图如下:
@@content@@
ID | 用户名 | 邮箱 |
---|---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 因为返回的是字符串所以我们可以对字符串进行拼接成html看得懂的,然后在从html转化为字节传给浏览器。
在f2中定义函数如下:
def f2(request):
创建连接
conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123456', db='myemployees')
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
# 在数据库查询数据
cursor.execute("SELECT employee_id,first_name,phone_number FROM employees")
# 获取所有查到的数据
user_list = cursor.fetchall()
# 关闭
cursor.close()
conn.close()
# 拼接
content_list = []
for row in user_list:tp = "<tr><td>%s</td><td>%s</td><td>%s</td></tr>" % (row['employee_id'], row['first_name'], row['phone_number'])# 添加进来content_list.append(tp)
# 拼接到一起
content = "".join(content_list)
# 打开userlist.html
f = open('动态网页/userlist.html', 'r', encoding='utf-8')
# 获得字符串(模板的渲染)
template = f.read()
# 关闭
f.close()
# 把我之前在html写的@@content@@修改
data = template.replace('@@content@@', content)
# 把写好的字符串转成字节的形式给浏览器渲染成可视化界面
return bytes(data, encoding='utf-8')
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
此时访问127.0.0.1:8080/userlist.htm
示意如下:
在这里插入图片描述
三.jinja2模板渲染
对于上面的一系列操作,相对麻烦,又要替换字符串,转字节,还得自己拼接,这时python中就出来了一个模块jinjia2,它可以帮助我们进行模板的渲染,而渲染的规则要和它一致。
安装jinja2模块
pip install jinja2
1
添加一个路由和函数
routers = [
(’/xxx’, f1),
(’/userlist.htm’, f2),
(’/host.html’,f3),
]
1
2
3
4
5
在动态网页/host.html中定义视图如下:
{% for row in user_list %} {% endfor %}
ID | 用户名 | 邮箱 |
---|---|---|
{{ row.employee_id }} | {{ row.first_name }} | {{ row.phone_number }} |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
在f3中定义函数如下:
from jinja2 import Template
def f3(request):
f = open(‘动态网页/host.html’, ‘r’, encoding=‘utf-8’)
# 获得字符串(模板的渲染)
data = f.read()
# 关闭
f.close()
# 创建连接
conn = pymysql.connect(host=‘127.0.0.1’, port=3306, user=‘root’, passwd=‘123456’, db=‘myemployees’)
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
# 在数据库查询数据
cursor.execute(“SELECT employee_id,first_name,phone_number FROM employees”)
# 获取所有查到的数据
user_list = cursor.fetchall()
# 关闭
cursor.close()
conn.close()
# 使用jinja2渲染
template=Template(data)
data=template.render(user_list=user_list)
# 上传
return data.encode(‘utf-8’)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
此时访问此时访问127.0.0.1:8080/host.html
示意如下:
在这里插入图片描述
python Django之Web框架本质 (2)相关推荐
- 西游之路——python全栈——Django的web框架本质
知识预览 Django基本命令 二 路由配置系统(URLconf) 三 编写视图 四 Template 五 数据库与ORM admin的配置 一 什么是web框架? 框架,即framework,特指为 ...
- Python之路--WEB框架本质
一.本质 众所周知,对于所有的Web应用,本质上其实就是一个socket服务端,用户的浏览器其实就是一个socket客户端. #!/usr/bin/env python #coding:utf-8im ...
- Python学习-基础篇14 Web框架本质及第一个Django实例
Web框架本质 我们可以这样理解:所有的Web应用本质上就是一个socket服务端,而用户的浏览器就是一个socket客户端. 这样我们就可以自己实现Web框架了. 半成品自定义web框架 impor ...
- 手撸web框架即引入框架思想,wsgierf模块,动静态网页,模板语法jinja2,python三大主流web框架,django安装,三板斧...
手撸web框架 web框架 什么是web框架? 暂时可理解为服务端. 软件开发架构 C/S架构 B/S架构 # 后端 import socketserver = socket.socket() # 不 ...
- Django基础-Web框架-URL路由
Django基础-Web框架-URL路由 一.Django基础–Web框架 MVC和MTV框架 MVC 把Web应用分为模型(M).视图(V).控制器(C)三层,他们之间以一种插件式的,松耦合的方式联 ...
- Django基础---Web框架、URL路由、视图函数、模板系统
文章目录 Django基础 Django基础---Web框架 MVC和MTV框架 MVC MTV Django下载与安装 基于Django实现一个简单的示例 get请求获取数据 post请求获取数据 ...
- py库: django (web框架)
py库: django (web框架) http://www.imooc.com/learn/736 Python-走进Requests库 http://www.imooc.com/learn/790 ...
- python四大主流web框架
python四大主流web框架 转载自博客:https://www.cnblogs.com/an-wen/p/11330834.html --爱文飞翔 Python 四大主流 Web 编程框架 目前P ...
- windows2008R2+IIS部署python Django的web环境
windows2008R2+IIS部署python Django的web环境 这篇文章写得非常好,非常仔细,作者把所有的坑都明确标识出来,可以少走很多弯路.感谢作者 潇洒哥Kahn 的辛苦付出. 这里 ...
最新文章
- 自动化测试框架设计模式
- tf.nn.softmax_cross_entropy_with_logits 和 tf.contrib.legacy_seq2seq.sequence_loss_by_example 的联系与区别
- java发送c语言结构体_C语言中结构体直接赋值?
- linux下部署Tesseract OCR及调用
- 【Spring框架】全集详解
- 手把手教你用WPE“修改”各种魔兽SF
- 如何生成唯一的Android设备ID?
- 计算机组装主板插线图,电脑组装之主板接口线缆怎么安装【图解教程】
- ES3、ES5、ES6、ES2016、ES2017、ES2018、ES2019
- 一、物流的基本概念|1.1物流的定义及作用
- 第一章 【教育基础知识和基本原理】
- Jmeter 压测和AB压测的比较
- 数据分析案例-数据科学相关岗位薪资可视化分析
- 艾媒咨询:2015年度中国智能路由器市场监测报告
- 前端大屏数据可视化示例
- dlt645数据读和写
- MySQL安装配置(Windows和 Linux )
- 北邮 python 学堂在线动态请求页面内容爬取
- 安卓APP跳转百度、高德、腾讯地图
- tomcat	400错误跳转自定义页面