python中web框架的自定义创建


Posted in Python onSeptember 08, 2019

一、什么是框架

框架的本质就是一个socket服务,可以完成不同主机之间的通信。它是一个半成品的项目,其中可能已经封装好了基本的功能,比如路由,模型,模板,视图功能都已完善,又可能它只封装好了基本的路由功能,其他的所有都需要程序员来完善。
优点:节省了开发时间,节约了开发人力,提高了开发效率

二、框架的种类

目前python开发市场上最常用的有三大框架,Django,flask与tornado。其中,Django是最常用的,它是一个重量级框架,其中的大部分功能都已经被封装完成,只需小小的逻辑代码,即可上线运行。但也正因为这样,Django框架相比较flask来说,比较臃肿,体态比较庞大,因此在一些小型网站的开发上,Django就显得有些大材小用了。
flask是一种轻量级框架,其中只完成了基本的路由功能,其他的所有都需要程序员去完善,或者借用第三方模块,因此,flask可以轻松应对小型网站的开发,但是对于大型网站,虽然也能实现功能,但是对程序员的程序功底要求的非常高。

区别:

Django使用app进行分模块开发,flask使用蓝图进行模块开发
Django使用的是MTV模式进行解耦合,flask没有很好的完成解耦合
Django有自己的模板和路由和orm,没有服务,使用的是wsgiref。
flask 只有自己的路由,模板使用jinja2。Orm使用的是flask-sqlalchemy 模块。
flask是轻量级框架,只封装了核心功能(路由),使用比较灵活。

注:

Django执行流程:

1.浏览器访问应用
2.通过路由系统找到对应的视图函数
3.对数据库进行操作
4.返回页面给浏览器。

三、框架的自定义

理解框架的底层是如何进行工作的,可以帮助我们更有效率的进行框架的使用。
在下面会进行逐步的说明,直至完成基本功能的实现
框架的本质:首先是基于socket进行服务端与客户端的通信,下面的代码是服务端,浏览器是客户端。

import socket
# 第一个参数代表基于网络,第二个参数表示基于tcp协议
server_sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#注意需要是元组对象,两个参数分别是url以及端口
server_sk.bind(('127.0.0.1', 9999))
#监听,并且最多允许128台客户机同时连接
server_sk.listen(128)
while True:
  print('等待客户端的链接:')
  #客户端发送过来的请求,是一个元组对象,将其进行解包
  clinet_sk, addr = server_sk.accept()
  content = clinet_sk.recv(1024) # 默认是二进制内容
  print(content) # 接收的到的内容是请求报文,
  #将接收到的二进制内容解码为字符串
  content = content.decode('utf-8')
  print(content)

  # 向浏览器发送内容
  msg1 = 'HTTP/1.1 200 ok\r\n'.encode('utf-8') # 设置响应首行
  msg2 = 'Content-Type:text/html;charset=utf-8\r\n'.encode('utf-8') # 设置响应头
  # 告诉浏览器,返回的是文本类型的html,并且以utf-8编码进行解码
  msg3 = '\r\n'.encode('utf-8') # 响应空行
  msg4 = '你好啊浏览器'.encode('utf-8') # 设置响应体
  client_sk.send(msg1)
  client_sk.send(msg2)
  client_sk.send(msg3)
  client_sk.send(msg4)
  client_sk.close()

在获取浏览器输入的url之后,可以根据不同的路径值给与不同的响应,这就是框架中的路由的作用。

import socket

server_sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_sk.bind(('127.0.0.1', 9999))
server_sk.listen(128)


def index(path):
  msg = 'this is a {} page'.format(path).encode('utf-8')
  return msg


def home(path):
  msg = '这是{}页面'.format(path).encode('utf-8')
  return msg


def error(path):
  msg = 'sorry {} 404 not found ...'.format(path).encode('utf-8')
  return msg


while True:
  client_sk, addrs = server_sk.accept()
  content = client_sk.recv(1024)
  content = content.decode('utf-8')
  print('客户端发来贺电:')
  print(content)
  header_lst = content.split('\r\n') # 按\r\n进行切割
  print(header_lst)
  title_lst = header_lst[0].split(' ') # 获取请求首行并按 空格 切割
  print(title_lst)
  path = title_lst[1] # 获取url中的路径部分
  print(path)
  if path == '/home':
    msg = home(path)
  elif path == '/index':
    msg = index(path)
  else:
    msg = error(path)

  # 向页面返回内容
  msg1 = 'HTTP/1.1 200 ok\r\n'.encode('utf-8')
  msg2 = 'Content-Type:text/html;charset=utf-8\r\n'.encode('utf-8')
  msg3 = '\r\n'.encode('utf-8')
  client_sk.send(msg1)
  client_sk.send(msg2)
  client_sk.send(msg3)
  client_sk.send(msg)
  client_sk.close()

在实际过程中,给浏览器返回前端页面时,是将HTML文件中的内容读取出来,以二进制的形式将其传递给浏览器,由浏览器解析后进行显示。

import socket

server_sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_sk.bind(('127.0.0.1', 9999))
server_sk.listen(128)

def index(path):
  with open('index.html', mode='rb') as f:
    msg = f.read()
  return msg
def home(path):
  with open('home.html', mode='rb') as f:
    msg = f.read()
  return msg
def error(path):
  with open('error.html', mode='rb') as f:
    msg = f.read()
  return msg
path_lst = [
  ('/index', index), # 注意写的是函数的地址,不是调用函数
  ('/home', home),
]
while True:
  client_sk, addrs = server_sk.accept()
  content = client_sk.recv(1024)
  content = content.decode('utf-8')
  print('客户端发来贺电:')
  print(content)
  header_lst = content.split('\r\n') # 按\r\n进行切割
  print(header_lst)
  title_lst = header_lst[0].split(' ') # 获取请求首行并按 空格 切割
  print(title_lst)
  path = title_lst[1] # 获取url中的路径部分
  func = None
  for path_tup in path_lst:
    if path_tup[0] == path:
      func = path_tup[1] # 将 对应函数地址赋值给func
      break
  if func:
    msg = func(path)
  else:
    msg = error(path)
  # 向页面返回内容
  msg1 = 'HTTP/1.1 200 ok\r\n'.encode('utf-8')
  msg2 = 'Content-Type:text/html;charset=utf-8\r\n'.encode('utf-8')
  msg3 = '\r\n'.encode('utf-8')
  client_sk.send(msg1)
  client_sk.send(msg2)
  client_sk.send(msg3)
  client_sk.send(msg)
  client_sk.close()

在上一步向浏览器返回具体页面的同时,可以将其中的某些数据进行替换,然后重新进行编码。这就是框架中{{}}的作用

import socket

server_sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_sk.bind(('127.0.0.1', 9999))
server_sk.listen(128)

def index(path):
  with open('index.html', mode='r', encoding='utf-8') as f:
    msg = f.read()
    msg = msg.replace('xxoo', path).encode('utf-8')
  return msg
def home(path):
  with open('home.html', mode='rb') as f:
    msg = f.read()
  return msg
def error(path):
  with open('error.html', mode='rb') as f:
    msg = f.read()
  return msg
path_lst = [
  ('/index', index), # 注意写的是函数的地址,不是调用函数
  ('/home', home),
]
while True:
  client_sk, addrs = server_sk.accept()
  content = client_sk.recv(1024)
  content = content.decode('utf-8')
  print('客户端发来贺电:')
  print(content)
  header_lst = content.split('\r\n') # 按\r\n进行切割
  print(header_lst)
  title_lst = header_lst[0].split(' ') # 获取请求首行并按 空格 切割
  print(title_lst)
  path = title_lst[1] # 获取url中的路径部分
  func = None
  for path_tup in path_lst:
    if path_tup[0] == path:
      func = path_tup[1] # 将 对应函数地址赋值给func
      break
  if func:
    msg = func(path)
  else:
    msg = error(path)
  # 向页面返回内容
  msg1 = 'HTTP/1.1 200 ok\r\n'.encode('utf-8')
  msg2 = 'Content-Type:text/html;charset=utf-8\r\n'.encode('utf-8')
  msg3 = '\r\n'.encode('utf-8')
  client_sk.send(msg1)
  client_sk.send(msg2)
  client_sk.send(msg3)
  client_sk.send(msg)
  client_sk.close()

到这里,框架的基本功能就已经实现了,在此基础上进行优化,将不同的功能分开存储,就可以实现框架的解耦合。就是框架的雏形。

上面写的都比较??拢?旅娓?桓霰冉暇?虻男捶?/p>

"""
框架的本质就是一个socket,完成了基本功能的封装,需要程序员去搞定逻辑部分
"""
import socket
#第一个参数表示基于网络,第二个表示基于tcp
socket_pro = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
# 设置URL及端口
socket_pro.bind(("127.0.1.1",8888))
# 最多可允许128个客户端同时连接
socket_pro.listen(128)
"""
在实际返回到某个页面的时候,并不是指向了此页面,
而是将页面中的内容以二进制形式读取出来,作为返回值传递到前端进行解析
"""
# 在实际中,我们需要将后台的数据传输到前端进行显示,因此在传输之前,就要将数据替换掉,
# 在传输前有一个读取的过程,在读取时,我们就可以将数据替换,然后重新进行编码为二进制,
# 就可以被客户端所解析,从而显示
def index(path):
  with open('index.html','r',encoding='utf-8') as fie:
    msg = fie.read()
    # fie.read()读取出来的内容为 字符串形式,要将其传到前端页面,就要再次进行编码
    msg = msg.replace('oooo',path).encode('utf-8')
    print(type(fie.read())) # <class 'str'>
  return msg
# 没有替换页面中数据时的读取方式
def home(path):
  with open('home.html','rb')as fie:
    msg = fie.read()
  return msg
def other():
  with open('other.html','rb')as fie:
    msg = fie.read()
  return msg
  
# 定义路由列表,类似于Django中url.py文件中的urlpatterns
urlpatterns = [
  ('/index',index),
  ('/home',home)
]
while True:
  print('等待客户端连接中')
  print('-----'*24)
  print(socket_pro.accept())
  print('*******'*24)
  # socket_pro.accept()返回的是一个元组
  socket_min,addr = socket_pro.accept()
  # 可接收1024个字节
  contents = socket_min.recv(1024)
  print(contents)
  print('========' * 24)
  contents = contents.decode('utf-8')
  print(contents)
  print('#########'*24)
  # 按\r\n进行分割
  header_lst = contents.split('\r\n')
  print('header:{}'.format(header_lst))
  print('+'*100)
  # 按空格进行分割,获取请求首行
  url_lst = header_lst[0].split(' ')
  print(url_lst)
  print('___----___'*24)
  # 获取用户输入的url路径
  url = url_lst[1]
  print(url)
  print('=+=+=+='*24)
  func = None
  # 循环获取urlpatterns列表中的元组对象
  for url_real in urlpatterns:
    # 如果从地址栏中获取的url与列表中的子子元素相同,说明该路径存在
    if url_real[0] == url:
      # 将urlpatterns中的视图函数名赋值给一个对象
      func = url_real[1]
      # 退出循环
      break
  if func:
    # 调用视图函数
    msg = func(url)
  else:
    msg = other()

  #响应,给客户端返回响应
  socket_min.send('http/1.2 200 error\r\n'.encode('utf-8'))
  socket_min.send('Content-Type:text/html;charset=utf-8\r\n'.encode('utf-8'))#设置响应头信息
  socket_min.send('\r\n'.encode('utf-8'))
  # 浏览器默认解码方式为gbk,可以使用响应头告诉浏览器解码方式
  # 返回给客户端一段响应
  socket_min.send(msg)
  # 关闭
  socket_min.close()

嗯,就到这里。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python中编写ORM框架的入门指引
Apr 29 Python
python清除字符串里非字母字符的方法
Jul 02 Python
Python工程师面试题 与Python Web相关
Jan 14 Python
Python实现的文本编辑器功能示例
Jun 30 Python
python实现二叉查找树实例代码
Feb 08 Python
Python KMeans聚类问题分析
Feb 23 Python
浅谈pandas筛选出表中满足另一个表所有条件的数据方法
Feb 08 Python
pandas DataFrame 交集并集补集的实现
Jun 24 Python
djano一对一、多对多、分页实例代码
Aug 16 Python
python 深度学习中的4种激活函数
Sep 18 Python
matplotlib阶梯图的实现(step())
Mar 02 Python
matplotlib如何设置坐标轴刻度的个数及标签的方法总结
Jun 11 Python
python web框架中实现原生分页
Sep 08 #Python
python中open函数的基本用法示例
Sep 07 #Python
Python3显示当前时间、计算时间差及时间加减法示例代码
Sep 07 #Python
利用python计算时间差(返回天数)
Sep 07 #Python
Django配置MySQL数据库的完整步骤
Sep 07 #Python
Django项目创建到启动详解(最全最详细)
Sep 07 #Python
Python笔试面试题小结
Sep 07 #Python
You might like
php ci框架中加载css和js文件失败的原因及解决方法
2014/07/29 PHP
初识laravel5
2015/03/02 PHP
PHP sleep()函数, usleep()函数
2016/08/25 PHP
PHP面向对象五大原则之依赖倒置原则(DIP)详解
2018/04/08 PHP
JavaScript的类型简单说明
2010/09/03 Javascript
DIV外区域Click后关闭DIV的实现代码
2011/12/21 Javascript
Jquery插件编写简明教程
2014/03/25 Javascript
Javascript实现多彩雪花从天降散落效果的方法
2015/02/02 Javascript
js拖拽的原型声明和用法总结
2016/04/04 Javascript
jQuery对checkbox 复选框的全选全不选反选的操作
2016/08/09 Javascript
用最简单的方法判断JavaScript中this的指向(推荐)
2017/09/04 Javascript
使用vue官方提供的模板vue-cli搭建一个helloWorld案例分析
2018/01/16 Javascript
JavaScript 五大常见函数
2018/03/23 Javascript
学习jQuery中的noConflict()用法
2018/09/28 jQuery
JS页面动态绘图工具SVG,Canvas,VML介简介
2020/10/16 Javascript
js实现缓动动画
2020/11/25 Javascript
在Python中使用zlib模块进行数据压缩的教程
2015/06/26 Python
深入讲解Python编程中的字符串
2015/10/14 Python
Python爬虫框架Scrapy基本用法入门教程
2018/07/26 Python
python实现录音小程序
2020/10/26 Python
深入理解Python中的 __new__ 和 __init__及区别介绍
2018/09/17 Python
Python编程深度学习绘图库之matplotlib
2018/12/28 Python
关于python下cv.waitKey无响应的原因及解决方法
2019/01/10 Python
python3实现zabbix告警推送钉钉的示例
2019/02/20 Python
python微信撤回监测代码
2019/04/29 Python
python爬虫模块URL管理器模块用法解析
2020/02/03 Python
pymysql之cur.fetchall() 和cur.fetchone()用法详解
2020/05/15 Python
Django如何使用asyncio协程和ThreadPoolExecutor多线程
2020/10/12 Python
5分钟实现Canvas鼠标跟随动画背景
2019/11/18 HTML / CSS
美国知名日用品连锁超市:Dollar General(多来店)
2017/01/14 全球购物
新加坡第一的杂货零售商:NTUC FairPrice
2020/12/05 全球购物
广告艺术设计专业自荐书
2014/07/08 职场文书
圣诞节开幕词
2015/01/29 职场文书
担保书格式范文
2015/09/22 职场文书
Nginx访问日志及错误日志参数说明
2021/03/31 Servers
2022漫威和DC电影上映作品
2022/04/05 欧美动漫