python就业班 miniweb框架_mini-web框架

1. 框架概述

web框架是一个为web服务器提供服务的应用程序,专门负责处理用户的动态资源请求.

静态资源: 资源的内容是固定不变的.

动态资源: 资源的内容是动态变化, 数据是从数据库获取的.

静态 web 服务器 使用 tcp 传输数据

1. 导包 socket

2. 创建一个 socket 对象, socket.socket()

端口复用(可选的)

3. 绑定 socket对象.bind((ip, 端口))

4. 监听 socket对象.listen()

5. 等待连接 socket对象.accept()---> 阻塞等待客户端连接,返回一个新的 socket 对象

6. 接收信息(请求报文) recv

7. 发送信息(响应报文) send

8. 关闭套接字 close()

------------------------------------------

web 服务器的工作流程

1. 在浏览器输入 URL 网址

2. 浏览器会访问 DNS 服务器, 做 DNS 解析, 将域名对应的 ip 进行返回

3. 和服务器建立连接(三次握手)

4. 发送请求报文

5. web 服务器接收浏览器发送报文, 解析报文, 判断请求的资源是静态资源还是动态资源

6. 如果是静态资源, web 服务器自己处理,将内容返回

7. 如果是动态资源, 需要将请求交给 web 框架处理

8. web 框架根据 web 服务器发送的请求, 从模板库中读取需要的模版文件, 同时还需要中数据库中查询需要的数据, 将数据和模版文件进行整合,组成完整的数据

9. web 框架将整理后的数据和处理结果发送给 web 服务器

10. web 服务器根据 web 框架发送内容,组成响应报文,发送给浏览器

11. 浏览器将资源进行整合, 显示内容

---5 7 8 9 10 写代码实现---

2. 搭建框架

1. 找到之前书写的静态 web 服务器的代码, 作为 web 服务器使用

import socket

import threading

class HTTPWebServer(object):

def __init__(self):

# 1. 创建 socket

server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 设置端口复用

server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)

# 2. 绑定端口和 ip

server_socket.bind(('', 8080))

# 3. 设置监听

server_socket.listen(128)

self.server_socket = server_socket # 将这个 socket 作为实例属性

def __del__(self): # 对象销毁的时候调用 close() 方法

self.server_socket.close()

@staticmethod

def __handle_client_request(new_soc, client_ip_port):

# 5. 接收信息(HTTP 请求报文)

buf = new_soc.recv(4096) # 一次性报文

if buf:

# 打印请求报文

# print(buf.decode())

buf = buf.decode()

# 6. 发送信息(HTTP 响应报文)

# 响应行 协议的版本 状态码 状态描述

response_line = "HTTP/1.1 200 OK\r\n"

# 响应头

response_header = "Server:PY\r\nName:py40\r\n"

# 空行(\r\n)

# 响应体, 文件的内容, 读取文件,将文件的内容作为响应体发送

file_name = buf.split(' ', 2)[1]

print(f"请求的资源为{file_name}")

# 访问的资源是 / ---> index.html

if file_name == '/':

file_name = '/index.html'

try:

with open('static' + file_name, 'rb') as f: # rb, 读取出来的直接是 bytes

data = f.read()

except FileNotFoundError:

with open('static/error.html', 'rb') as f:

data = f.read()

# 如果文件不存在, 修改响应行的状态码

response_line = "HTTP/1.1 404 Not Found\r\n"

response = (response_line + response_header + '\r\n').encode() + data

new_soc.send(response)

else:

print(f"{client_ip_port} 断开连接...")

# 7. 关闭连接

new_soc.close()

def start(self):

# 4. 等待连接

print('服务已启动,端口为 8080, 等待连接....')

while True:

new_socket, ip_port = self.server_socket.accept()

print(f"{ip_port} 建立连接......")

# 用户连接之后,创建一个线程

sub_thread = threading.Thread(target=self.__handle_client_request, args=(new_socket, ip_port))

sub_thread.start()

if __name__ == '__main__':

# 创建对象

web = HTTPWebServer()

web.start() # 启动服务器

2. 将 static 文件和 template 文件放到当天的代码目录中

3. 启动 web 服务器, 访问之前的静态页面, 能够正常访问

4. 修改 web 服务器的代码

3. 动态资源判断

判断一个资源是不是动态资源, 只需要判断资源是不是以 .html 结尾 字符串.endswith()

# 此时获取到文件的资源路径,需要判断是静态资源还是动态资源

if file_name.endswith('.html'):

"""动态资源, 交给框架处理"""

# 思考,框架如何知道请求的是哪个页面 ---> 函数传参

# 一般的方法, 将需要传递的数据组成字典传递

# 好处: 可以传递多个数据

env = {

'filename': file_name,

# 还可以传递其他参数,目前不需要

}

status, header, file_data = framework.handle_request(env)

response_line = "HTTP/1.1%s\r\n" % status

response_header = header

data = file_data.encode()

else:

"""静态资源,web 服务器直接自己处理"""

try:

with open('static' + file_name, 'rb') as f: # rb, 读取出来的直接是 bytes

data = f.read()

except FileNotFoundError:

with open('static/error.html', 'rb') as f:

data = f.read()

# 如果文件不存在, 修改响应行的状态码

response_line = "HTTP/1.1 404 Not Found\r\n"

4. 处理客户端的动态资源请求创建web框架程序

接收web服务器的动态资源请求

处理web服务器的动态资源请求并把处理结果返回给web服务器

web服务器把处理结果组装成响应报文发送给浏览器

web框架程序(framework.py)代码:

"""miniweb框架,负责处理动态资源请求"""

import time

# 获取首页数据

def index():

# 响应状态

status = "200 OK";

# 响应头

response_header = [("Server", "PWS2.0")]

# 处理后的数据

data = time.ctime()

return status, response_header, data

# 没有找到动态资源

def not_found():

# 响应状态

status = "404 Not Found";

# 响应头

response_header = [("Server", "PWS2.0")]

# 处理后的数据

data = "not found"

return status, response_header, data

# 处理动态资源请求

def handle_request(env):

# 获取动态请求资源路径

request_path = env["filename"]

print("接收到的动态资源请求:", request_path)

if request_path == "/index.html":

# 获取首页数据

result = index()

return result

else:

# 没有找到动态资源

result = not_found()

return result

5. 路由列表开发

路由: 请求的 URL 到到处理的函数之间的关系

5.1 在路由列表添加路由

# 定义路由列表, 在列表中保存所有的请求资源和处理函数的对应关系(Django)

route_list = [

('/index.html', index), # 函数地址的引用, 不能加括号的

('/center.html', center)

]

def handle_request(env):

"""处理动态资源请求"""

# 1. 获取web 服务器传递的参数

file_name = env['filename'] # 通过字典的key 取值

print(f'接收到要处理的动态资源是: {file_name}')

# 遍历路由列表, 查找需要请求的资源是否在路由列表中

for route in route_list:

if file_name == route[0]:

func = route[1] # func 是一个函数

return func() # return route[1]()

else:

return not_found()

5.2 装饰器方式的添加路由

route_list = []

def my_route(filename):

# 定义装饰器

def decorator(fn):

# 添加路由

# route_list.append((filename, fn))

def inner():

return fn()

route_list.append((filename, inner))

return inner

return decorator

@my_route('/index.html')

def index(): # 视图函数

"""专门用来处理首页数据的"""

# 1. 从模板库读取 html 页面

with open('template/index.html', 'r') as f:

file_data = f.read()

6. 数据库准备将提前给到大家的 stock_db.sql 复制到 Ubuntu 桌面中

登录 mysql 客户端 mysql -uroot -pmysql

创建数据库 create database stock_db charset=utf8;

使用这个数据库use stock_db

导入 SQL 语句 source ~/Desktop/stock_db.sql

7. index 页面处理从数据库获取数据

使用这个数据进行模版替换

# 获取首页数据

@route("/index.html")

def index():

# 响应状态

status = "200 OK";

# 响应头

response_header = [("Server", "PWS2.0")]

# 打开模板文件,读取数据

with open("template/index.html", "r") as file:

file_data = file.read()

# 处理后的数据, 从数据库查询

conn = pymysql.connect(host="localhost",

port=3306,

user="root",

password="mysql",

database="stock_db",

charset="utf8")

# 获取游标

cursor = conn.cursor()

# 查询sql语句

sql = "select * from info;"

# 执行sql

cursor.execute(sql)

# 获取结果集

result = cursor.fetchall()

print(result)

data = ""

for row in result:

data += '''

%s%s%s%s%s%s%s%s''' % row

# 替换模板文件中的模板遍历

result = file_data.replace("{%content%}", data)

return status, response_header, result

8. center 页面处理

前后端分离后端程序员提供数据接口

前端程序员,在页面 发送 Ajax 请求,获取数据,解析数据,将数据显示到页面中

8.1 后端

# 个人中心数据接口开发

@route("/center_data.html")

def center_data():

# 响应状态

status = "200 OK";

# 响应头

response_header = [("Server", "PWS2.0"), ("Content-Type", "text/html;charset=utf-8")]

conn = pymysql.connect(host="localhost",

port=3306,

user="root",

password="mysql",

database="stock_db",

charset="utf8")

# 获取游标

cursor = conn.cursor()

# 查询sql语句

sql = '''select i.code, i.short, i.chg,i.turnover, i.price, i.highs, f.note_infofrom info as i inner join focus as f on i.id = f.info_id;'''

# 执行sql

cursor.execute(sql)

# 获取结果集

result = cursor.fetchall()

# 关闭游标

cursor.close()

# 关闭数据库连接

conn.close()

# 个人中心数据列表

center_data_list = list()

# 遍历每一行数据转成字典

for row in result:

# 创建空的字典

center_dict = dict()

center_dict["code"] = row[0]

center_dict["short"] = row[1]

center_dict["chg"] = row[2]

center_dict["turnover"] = row[3]

center_dict["price"] = str(row[4])

center_dict["highs"] = str(row[5])

center_dict["note_info"] = row[6]

# 添加每个字典信息

center_data_list.append(center_dict)

# 把列表字典转成json字符串, 并在控制台显示

json_str = json.dumps(center_data_list,ensure_ascii=False)

print(json_str)

return status, response_header, json_str

代码说明:json.dumps函数把字典转成json字符串

函数的第一个参数表示要把指定对象转成json字符串

参数的第二个参数ensure_ascii=False表示不使用ascii编码,可以在控制台显示中文。

响应头添加Content-Type表示指定数据的编码格式

8.2 前端

// 发送ajax请求获取个人中心页面数据

$.get("center_data.html", function (data) {

var data_array = data;

// 获取table标签对象

var $table = $(".table")

for(var i = 0; i < data_array.length; i++){

// 获取每一条对象

var center_obj= data_array[i];

var row_html= '

' +

'

'+ center_obj.code +'' +

'

'+ center_obj.short +'' +

'

'+ center_obj.chg +'' +

'

'+ center_obj.turnover +'' +

'

'+ center_obj.price +'' +

'

'+ center_obj.highs +'' +

'

'+ center_obj.note_info +'' +

'

修改 ';

// 为table标签添加每一行组装的html数据

$table.append(row_html);

}

}, "json");

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/337142.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java编写应用程序_为您的Java应用程序编写数据驱动的测试

java编写应用程序JUnit是一个功能非常强大的测试框架&#xff0c;它不仅为其用户提供了编写快速简便的测试的功能&#xff0c;而且还为用户提供了扩展它并使其按其期望的方式工作的机会。 在JUnit之上构建了许多框架&#xff0c;这些框架为目标受众提供了各种易用的功能。 Eas…

C语言如何知自身函数的实际地址与大小

点击蓝字关注我们因公众号更改推送规则&#xff0c;请点“在看”并加“星标”第一时间获取精彩技术分享来源于网络&#xff0c;侵删事情的起因大概是这样……在很久很久以前&#xff0c;我最早用的是MASM&#xff08;Win32ASM&#xff09;写程序&#xff0c;从平台兼容性、开发…

python快速排序算法循环_算法:快速排序的Python实现

一、概述快速排序(quick sort)是一种分治排序算法。该算法首先 选取 一个划分元素(partition element&#xff0c;有时又称为pivot)&#xff1b;接着重排列表将其 划分 为三个部分&#xff1a;left(小于划分元素pivot的部分)、划分元素pivot、right(大于划分元素pivot的部分)&a…

xtext_使用Xtext为Eclipse和IntelliJ开发DSL

xtext在这篇文章中&#xff0c;我们将看到如何开发一种简单的语言。 我们的目标是&#xff1a; 语言的解析器 IntelliJ的编辑器 。 编辑器应具有语法突出显示&#xff0c;验证和自动完成功能 我们还将免费提供Eclipse和Web编辑器的编辑器 &#xff0c;但请包含您的兴奋之处&…

sed 插入多行_Linux三剑客之sed

sed命令用法小记版本&#xff1a;CentOS7▼ ▼ ▼ ▼ ▼ ▼ ▼ ▼ ▼好久没更新文章了&#xff0c;项目的事情太多&#xff0c;总得给自己的懒惰找个借口&#xff0c;哈哈~话不多说进入正题创建测试数据[aliscaspark02 a]$ cat data#test the sedThis is the header l…

分享一些超级炫酷的C语言小技巧

点击蓝字关注我们因公众号更改推送规则&#xff0c;请点“在看”并加“星标”第一时间获取精彩技术分享来源于网络&#xff0c;侵删C语言常常让人觉得它所能表达的东西非常有限。它不具有类似第一级函数和模式匹配这样的高级功能。但是C非常简单&#xff0c;并且仍然有一些非常…

使用Apache Cassandra设置SpringData项目

在这篇文章中&#xff0c;我们将使用Gradle和spring boot来创建一个集成spring-mvc和Apache Cassandra数据库的项目。 首先&#xff0c;我们将从Gradle配置开始 group com.gkatzioura version 1.0-SNAPSHOTapply plugin: java apply plugin: eclipse apply plugin: idea appl…

优朋普乐大数据_优朋普乐邵以丁:用大数据全面洞察需求

优朋普乐创始人、董事长兼CEO邵以丁回顾优朋普乐十二年发展历程&#xff0c;数次强调是多年来积累的大数据给优朋普乐的业务拓展指明了方向&#xff0c;有的放矢的决策让企业对未来发展充满信心。大数据为及时发现甚至准确预测消费需求提供了新途径&#xff0c;因为基于相关的大…

C++编程新手容易犯的 10 种编程错误

点击蓝字关注我们因公众号更改推送规则&#xff0c;请点“在看”并加“星标”第一时间获取精彩技术分享来源于网络&#xff0c;侵删公司每年都会有一定的人员流动&#xff0c;相应地也会招一些应届生补充进来&#xff0c;指导应届生已经成为老员工的必修课了。平日里会我们会经…

drill apache_Apache Drill:如何创建新功能?

drill apacheApache Drill允许用户使用ANSI SQL探索任何类型的数据。 这很棒&#xff0c;但是Drill的作用远远不止于此&#xff0c;它允许您创建自定义函数来扩展查询引擎。 这些自定义函数具有Drill基本操作的所有性能&#xff0c;但是允许执行这些性能会使编写这些函数的技巧…

python往npy写入数据_Python 存取npy格式数据实例

数据处理的时候主要通过两个函数(1):np.save(“test.npy”&#xff0c;数据结构) ----存数据(2):data np.load(test.npy") ----取数据给2个例子如下(存列表)1、z [[[1, 2, 3], [w]], [[1, 2, 3], [w]]]np.save(test.npy, z)x np.load(test.npy) x:->array([[list([1,…

Linux上C语言程序编译过程详解

点击蓝字关注我们因公众号更改推送规则&#xff0c;请点“在看”并加“星标”第一时间获取精彩技术分享来源于网络&#xff0c;侵删本文将介绍如何将高层的C/C语言编写的程序转换成为处理器能够执行的二进制代码的过程&#xff0c;包括四个步骤&#xff1a;预处理&#xff08;P…

hibernate 别名_Hibernate:在sqlRestriction上使用联接表别名

hibernate 别名如果在复杂查询的情况下使用Hibernate模式&#xff0c;则需要使用sql。 因此&#xff0c;sqlRestrictions可以解决。 但是&#xff0c;对联接表别名使用sql限制有点棘手。 将有三个表&#xff1a; 公司表。 员工表。 每个员工都属于一个公司&#xff0c;因此…

C语言,动图展示十大经典排序算法

点击蓝字关注我们因公众号更改推送规则&#xff0c;请点“在看”并加“星标”第一时间获取精彩技术分享来源于网络&#xff0c;侵删以前也零零碎碎发过一些排序算法&#xff0c;但排版都不太好&#xff0c;又重新整理一次&#xff0c;排序算法是数据结构的重要部分&#xff0c;…

python求偏度系数_用 Python 讲解偏度和峰度

之前笔者在做一个金融数据项目时,有朋友问我,衡量股票收益率有没有什么好的方法。这个问题让笔者也思索了好久,其实股票的收益率如果我们从本质来看不就是数据吗,无非就是收益率我们就想让其越高越好,也就是让这个数据增加得越多越好。而衡量数据我们经常用到的方法有均值…

java ee各类组件_在Java EE组件中使用骆驼路线

java ee各类组件从现在开始我一直在与Camel合作&#xff0c;我真的很喜欢它的简单性。 在Java EE之上使用它一直是一个挑战&#xff0c;我最近发表了一篇关于如何做到这一点的演讲&#xff0c;而在Java EE中引导Camel的不同方法实际上建议使用WildFly-Camel Subsystem 。 在正在…

5gnr帧结构特点有哪些_真空离子束刻蚀设备的结构特点有哪些

离子束刻蚀设备有立式、卧式两种结构。通常情况下&#xff0c;该设备以卧式的结构居多&#xff0c;因为采用卧式结构的话&#xff0c;离子源发出的离子束为水平喷射方向&#xff0c;大部分的刻蚀溅射物将落在真空室的底部&#xff0c;可在一定程度上将溅射材料的重新沉积减少。…

老了就不能编程?大龄程序员在线“辟谣”:15 年后,我变得更好了

点击蓝字关注我们因公众号更改推送规则&#xff0c;请点“在看”并加“星标”第一时间获取精彩技术分享来源于网络&#xff0c;侵删几年前&#xff0c;Quora 上的一个提问在程序员圈内掀起热议&#xff1a;“随着年龄的增长&#xff0c;人们会对编程失去兴趣吗&#xff1f;预计…

wildfly管理控制台_WildFly管理控制台已更新–请求反馈

wildfly管理控制台红帽JBoss企业应用程序平台&#xff08;EAP&#xff09;和WildFly具有共生关系 。 简而言之&#xff0c;红帽JBoss企业应用程序平台&#xff08;JBoss EAP&#xff09;保留了WildFly社区项目&#xff08;以前称为JBoss Application Server&#xff09;的所有创…

linux 的ip 设置lo_Linux服务器设置静态IP的方法

这里以CentOS 7系列为例设置静态IP&#xff0c;原来RedHat系列的Linux发行版可以通过setup工具方便的设置静态IP&#xff0c;但是在版本7之后setup工具的功能就逐渐减弱了&#xff0c;所以这时候采用修改配置文件的方式来设置静态IP&#xff0c;方法如下&#xff1a;首先注意&a…