01Web框架

【一】Web框架本质

将前端、数据库整合到一起的基于互联网传输的python代码
web框架也可以简单的理解为是软件开发架构里面的'服务端'
1.服务端
import socket
server=socket.socket()
server.bind(('127.0.0.1',8080))
server.listen(5)
while True:
    sock,addr=server.accept()
    data=sock.recv(1024)
    sock.send(b"xxxx")
2.客户端
import socket
client=socket.socket()
client.connect(('127.0.0.1',8080))
while True:
    client.send(b'ssss')
    data=client.recv(1024)
3.http协议
1.四大特性
    1.无状态
    2.应用层协议
    3.服务器只能响应客服端请求,客服端发起请求
    4.短链接
    5.持久连接
2.数据格式
(1)请求格式
     客户端给服务端发送消息应该遵循的数据格式 
        请求首行(请求方法  请求路径  协议版本)
        请求头(一大堆k:v键值对)
        (换行不能省略)
        请求体(携带敏感数据:密码 身份照号...) 不是一直都有
 (2) 响应格式
    服务端给客户端发送消息应该遵循的数据格式 
        响应首行(响应状态码 协议版本)
        响应头(一大堆k:v键值对)
        (换行不能省略)
        响应体(给浏览器展示给用户看的页面内容)
3.响应状态码
​
| 状态码类型  | 描述                                 
| 1xx       | 告诉客户端,本次请求,服务端还在持续处理中,并**没有结束**。 
| 2xx       | 告诉客户端,本次请求,服务端已经接收并**成功受理**了。
| 3xx       | 告诉客户端,服务端位置发生改变,希望客户端**重定向**访问跳转新的服务器地址进行请求 
| 4xx       | 告诉**客户端**,本次**请求有误**,服务器无法处理。
| 5xx       | 告诉客户端,本次请求服务端在处理过程中**服务端出错**了。    
4.基于不同的后缀响应不同的内容
服务端
import socket
​
​
server = socket.socket()
server.bind(('127.0.0.1', 8082))
server.listen(5)
​
​
while True:
    sock, addr = server.accept()
    data = sock.recv(1024)
    # 将请求相关数据先转成字符串
    data_str = data.decode('utf8')  # 'GET /login HTTP/1.1\r\nHost: 127.0.0.1:8081\r\n......'
    sock.send(b'HTTP1.1 200 OK\r\n\r\n')
    # 然后去字符串中截取出我们需要的内容(按照空格切割字符串 获取第二个元素即可)
    current_path = data_str.split(' ')[1]
    # 根据后缀的不同返回不同的内容
    if current_path == '/login':
        sock.send(b'hello login!!!')
    elif current_path == '/register':
        sock.send(b'hello register')
    else:
        sock.send(b'404 error')

【二】基于wsgiref模块搭建web框架

# 1.利用模块搭建服务端
# 2.利用模块处理好的HTTP字典数据编写业务
    查找用户url后缀对象的键值对数据
from wsgiref import simple_server
​
​
def run(request, response):
    """
    :param request: 请求相关的数据
    :param response: 响应相关的数据
    :return: 返回给客户端的展示数据
    """
    # print(request)  # 字典类型的数据(模块自动处理HTTP请求数据 便于后续数据获取)
    response('200 OK', [])  # 固定编写 无需掌握
    current_path = request.get("PATH_INFO")
    if current_path == '/login':
        return [b'hello login html']
    elif current_path == '/register':
        return [b'hello register html']
    return [b'404 error']
​
​
if __name__ == '__main__':
    server = simple_server.make_server('127.0.0.1', 8080, run)
    '''一致监听本机8080端口 一旦有请求访问 自动触发run方法的执行'''
    server.serve_forever()
1.优化
(1)问题
    如果网站很多,必须人为的添加elif
    每个分支下的功能根据业务逻辑的不同可能会比较复杂的逻辑
(2)函数优化
    ● 将匹配和功能封装成 元组和函数
    ● 但是还是会存在问题
      ○ 所有的代码全部放在一个py文件过于冗余
      ○ 不便于后期管理维护
(3)模块优化
    根据功能的不同拆分成不同的py文件
        urls.py                     对应关系的存储
        views.py                    业务逻辑的编写
● 以后要想新增功能 只需要在urls.py中添加对应关系 view.py中编写函数
● 但还是会存在新的问题
  ○ 业务函数的代码中 可能会频繁的使用到不同的html页面
为了避免文件类型的混乱 单独开设一个文件夹存储所有的html文件
    templates文件夹        存储项目所需的html文件
(5)静态优化
    html所学的css、js、第三方框架代码都是写完之后很少做改动的文件
    所以可以统一存放在某个文件夹下
        static文件夹               存储项目所需的'静态文件'(后续再讲)
优化实现
from wsgiref import simple_server
​
​
def register(request):
    return 'register'
​
​
def login(request):
    return 'login'
​
​
def error(request):
    with open(r'templates/error.html', 'r', encoding='utf8') as f:
        return f.read()
​
​
urls = (
    ('/login', login),
    ('/register', register)
)
​
​
def run(request, response):
    # run函数体中添加下列代码
    current_path = request.get("PATH_INFO")
    func_name = None
    for url_tuple in urls:
        if current_path == url_tuple[0]:
            # 先获取对应的函数名
            func_name = url_tuple[1]
            # 一旦匹配上了 后续的对应关系就无需在循环比对了
            break
    # for循环运行完毕之后 func_name也有可能是None
    if func_name:
        res = func_name(request)
    else:
        res = error(request)  # 顺手将request也传给函数 便于后续数据的获取
    return [res.encode('utf8')]
​
​
if __name__ == '__main__':
    '''服务端监听的IP和端口'''
    IP = '127.0.0.1'
    PORT = 8080
    '''创建一个服务端对象'''
    server = simple_server.make_server(IP, PORT, run)
    '''监听本机8080端口 一旦有请求访问 自动触发run方法的执行'''
    server.serve_forever()
    # 模块封装了socket代码并将请求数据处理成诸多k:v键值对
优化版本分层
[1]views.py
● --存储路由与函数对应关系(写相应函数的)

# 功能函数
def register(request):
    return 'register'


def login(request):
    return 'login'


def index(request):
    return 'index'


def error(request):
    with open(r'templates/error.html', 'r', encoding='utf8') as f:
        return f.read()
[2]urls.py
● --存储函数--》映射到view层的函数
from views import *

# 后缀匹配
urls = (
    ('/register', register),
    ('/login', login),
    ('/index', index),
)
[3]server.py
● --存储启动及分配代码---》启动的
from wsgiref import simple_server
from urls import urls
from views import error


def run(request, response):
    response('200 OK', []) 
    current_path = request.get("PATH_INFO")
    func_name = None
    for url_tuple in urls:  # ('/register', register)
        if current_path == url_tuple[0]:
            func_name = url_tuple[1]
            break
    if func_name:
        res = func_name(request)
    else:
        res = error(request) 
    return [res.encode('utf8')]


if __name__ == '__main__':
    server = simple_server.make_server('127.0.0.1', 8080, run)
    server.serve_forever()
2.模板文件与静态文件
[1]templates文件夹

--存储html文件

[2]static文件夹

--存储html页面所需静态资源(后续详细讲解或自行百度)

【三】动静态网页

静态网页
	页面上的数据是直接写死的 万年不变
  	eg:编写的 html
动态网页
	页面上的数据是通过代码动态获取的 实时可变
  	eg:
      1.页面上展示当前时间(后端获取传递给前端界面)
      2.页面上展示数据库数据(后端链接数据库查询数据再传递给页面)
  
● 静态网页适合用于内容较少且不需要频繁更新的场景,如关于我们、联系我们等基础介绍页面。
● 动态网页则更适用于需要实时交互、内容丰富且需要定期更新的场景,如新闻资讯、在线购物平台等,通过服务器端的动态处理,提供了更好的用户体验和更高的业务复杂性处理能力。

【四】Jinja2模板语法

1.案例--》页面展示当前时间
后端
def get_time(request):
    # 1.获取当前时间
    import time
    c_time = time.strftime('%Y-%m-%d %X')
    # 2.读取html文件
    with open(r'templates/get_time.html','r',encoding='utf8') as f:
        data = f.read()
    # 3.思考:如何给字符串添加一些额外的字符串数据>>>:字符串替换
    new_data = data.replace('random_str',c_time)
    return new_data
前端
<h1>展示后端获取的时间数据</h1>
<span>random_str</span>
2.jinja2模板语法--》写上述案例
1.views.py--》写功能函数的
from jinja2 import Template
def get_dict(request):
    user_dict = {'name': 'dream', 'pwd': 123, 'hobby': 'read'}
    new_list = [11, 22, 33, 44, 55, 66]
    with open(r'templates/get_dict.html', 'r', encoding='utf8') as f:
        data = f.read()
    temp_obj = Template(data)
    res = temp_obj.render({'user':user_dict,'new_list':new_list})
    return res
2.templates---》写html的
<h1>字典数据展示</h1>
<p>{{ user }}</p>
<p>{{ user.name }}</p>
<p>{{ user['pwd'] }}</p>
<p>{{ user.get('hobby') }}</p>
<h1>列表数据展示</h1>
<p>
    {% for i in new_list%}
        <span>元素:{{ i }}</span>
    {% endfor %}
</p>

【五】关键字

1.urls.py
● 后缀与函数名对应关系 
  ○ ('/index',register)
  ○ 后缀专业名词称之为'路由'
  ○ 函数名专业名词称之为'视图函数'
  ○ urls.py专业名词称之为'路由层'
2.views.py
● 专门编写业务逻辑代码 
  ○ 可以是函数 也可以是类
  ○ 函数专业名词称之为'视图函数'
  ○ 类专业名词称之为'视图类'
  ○ views.py专业名词称之为'视图层'
3.templates文件夹
● 专门存储html文件
● html文件专业名词称之为'模板文件'
● templates文件夹专业名词称之为'模板层'
4.static文件夹
● 专门存储静态文件资源 
  ○ 页面所需css文件、js文件、图片文件、第三方文件可统称为'静态资源'

【六】python主流web框架

### 【1】Django框架

- Django框架比较完整并且大
- 大而全
- 笨重

### 【2】flask框架

- 小而精
- 依赖于第三方模块

### 【3】Tornado框架

- 速度比较快
- 游戏服务器上

### 【4】fastapi框架

- 支持异步,比较快
- 内置了很多高级的功能

【七】网络框架和MVC架构

1.网络架构
	网络架构其实就是人家帮我们封装好底层源码调用后的框架
2.MVC架构
# Model - View - Controller

# 模型 - 视图 - 控制器

(1)模型(Model)
# 用于封装与应用程序的业务逻辑相关的数据及对数据的处理方法,是Web应用程序中用于处理应用程序的数据逻辑的部分,Model只提供功能性的接口,通过这些接口可以获取Model的所有功能。
# Model不依赖于View和Controller,它们可以在任何时候调用Model访问数据。
# 有些Model还提供了事件通知机制,为在其上注册过的View或Controller提供实时的数据更新。

# (2)视图(View)
# 负责数据的显示和呈现,View是对用户的直接输出。
# MVC中的一个Model通常为多个View提供服务。
# 为了获取Model的实时更新数据,View应该尽早地注册到Model中。

#(3)控制器(Controller)
# 负责从用户端收集用户的输入,可以看成提供View的反向功能。
# 当用户的输入导致View发生变化时,这种变化必须是通过Model反映给View的。
# 在MVC架构下,Controller一般不能与View直接通信,这样提高了业务数据的一致性,即以Model作为数据中心。

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值