手写web框架
| """ |
| web框架:将前端、数据库整合到一起的基于互联网传输的python代码 |
| web框架也可以简单的理解为是软件开发架构里面的'服务端' |
| """ |
| |
| socket模块 |
| |
| 四大特性、数据格式、响应状态码 |
| |
| 如何获取用户输入的url后缀>>>:HTTP请求数据 |
| /favicon.ico直接忽略 不影响判断 |
| 利用字符串切割和索引取值获取相应数据 |
| 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') |
| |
| 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') |
| |
| """ |
| 上述框架缺陷: |
| 1.服务端起始代码过于重复 |
| 2.针对HTTP请求数据没有完善的处理方式 |
| 3.并发量问题 |
| """ |
wsgiref 模块
| |
| |
| 查找用户url后缀对象的键值对数据 |
| from wsgiref import simple_server |
| |
| |
| def run(request, response): |
| """ |
| :param request: 请求相关的数据 |
| :param response: 响应相关的数据 |
| :return: 返回给客户端的展示数据 |
| """ |
| |
| 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.如果网站很多 是不是就是以为的添加elif |
| 2.每个分支下的功能根据业务逻辑的不同可能会比较复杂 |
| """上述两个问题需要做优化处理""" |
| 将匹配和功能封装成 元组和函数 |
| """所有的代码全部放在一个py文件过于冗余 不便于后期管理维护""" |
| 根据功能的不同拆分成不同的py文件 |
| urls.py 对应关系的存储 |
| views.py 业务逻辑的编写 |
| |
| """业务函数的代码中 可能会频繁的使用到不同的html页面""" |
| 为了避免文件类型的混乱 单独开设一个文件夹存储所有的html文件 |
| templates文件夹 存储项目所需的html文件 |
| """项目中的html文件 也有可能需要用到css、js、第三方框架文件""" |
| html所学的css、js、第三方框架代码都是写完之后很少做改动的文件 所以可以统一存放在某个文件夹下 |
| static文件夹 存储项目所需的'静态文件'(后续再讲) |
| |
| |
| 基于上述优化之后 整个项目结构清晰 管理维护都很方便!!! |
动静态网页
| 静态网页 |
| 页面上的数据是直接写死的 万年不变 |
| eg:上述项目中编写的 error.html func.html |
| 动态网页 |
| 页面上的数据是通过代码动态获取的 实时可变 |
| eg: |
| 1.页面上展示当前时间(后端获取传递给前端界面) |
| 2.页面上展示数据库数据(后端链接数据库查询数据再传递给页面) |
| |
| 案例1: 页面上展示当前时间 |
| def get_time(request): |
| |
| import time |
| c_time = time.strftime('%Y-%m-%d %X') |
| |
| with open(r'templates/get_time.html','r',encoding='utf8') as f: |
| data = f.read() |
| |
| new_data = data.replace('asdaksdjal',c_time) |
| return new_data |
| |
| 案例2: 将字典传递给页面 并且在页面上 还可以使用字典的操作方法 |
| jinja2模板语法 |
jinja2 模块
| |
| pip3 install jinja2 |
| |
| 在编写前后端不分离项目的时候 可以使用该模块提供的模板语法简单快速的在html页面是使用类似于后端的代码语法操作数据 |
| |
| '''目前只做简单了解 后面都会详细的讲!!!''' |
| temp_obj.render({'user':user_dict,'new_list':new_list}) |
| |
| <p>{{ user }}</p> |
| <p>{{ user.name }}</p> |
| <p>{{ user['pwd'] }}</p> |
| <p>{{ user.get('hobby') }}</p> |
| |
| {% for i in new_list %} |
| <span>元素:{{ i }}</span> |
| {% endfor %} |
| |
| 还是用的上述模板语法 |
代码实现以上问题
| 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) |
| data_str = data.decode('utf8') |
| """ |
| GET /register HTTP/1.1 |
| Host: 127.0.0.1:8080 |
| Connection: keep-alive |
| Cache-Control: max-age=0 |
| sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="100", "Google Chrome";v="100" |
| sec-ch-ua-mobile: ?0 |
| sec-ch-ua-platform: "Windows" |
| Upgrade-Insecure-Requests: 1 |
| User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36 |
| Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 |
| Sec-Fetch-Site: none |
| Sec-Fetch-Mode: navigate |
| Sec-Fetch-User: ?1 |
| Sec-Fetch-Dest: document |
| Accept-Encoding: gzip, deflate, br |
| Accept-Language: zh-CN,zh;q=0.9 |
| """ |
| print(data_str) |
| |
| sock.send(b'HTTP1.1 200 OK\r\n\r\n') |
| c_path = data_str.split(' ')[1] |
| if c_path == '/login': |
| sock.send(b'login') |
| elif c_path == '/register': |
| sock.send(b'register') |
| elif c_path == '/index': |
| sock.send(b'index') |
| else: |
| sock.send(b'404 error') |
| from wsgiref import simple_server |
| from urls import urls |
| from views import error |
| |
| def run(request, response): |
| """ |
| :param request: 请求相关数据 |
| :param response: 响应相关数据 |
| :return: 返回客户端的数据 |
| """ |
| |
| response('200 OK', []) |
| c_path = request.get("PATH_INFO") |
| |
| |
| |
| |
| |
| |
| |
| |
| func_name = None |
| for url_tuple in urls: |
| if c_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) |
| '''持续监听本机8080端口,一旦有请求访问,自动触发run方法''' |
| server.serve_forever() |
框架请求流程
| 参考群内截图:仅限于我们自己编写的web框架(真正的框架其实跟这个差不多) |
| |
| urls.py |
| 后缀与函数名对应关系 |
| ('/index',register) |
| 后缀专业名词称之为'路由' |
| 函数名专业名词称之为'视图函数' |
| urls.py专业名词称之为'路由层' |
| |
| views.py |
| 专门编写业务逻辑代码 |
| 可以是函数 也可以是类 |
| 函数专业名词称之为'视图函数' |
| 类专业名词称之为'视图类' |
| views.py专业名词称之为'视图层' |
| |
| templates文件夹 |
| 专门存储html文件 |
| html文件专业名词称之为'模板文件' |
| templates文件夹专业名词称之为'模板层' |

python主流框架
| django |
| 大而全 自带的功能非常的多 但是有时候会略显笨重 |
| 类似于'航空母舰' |
| |
| flask |
| 小而精 自带的功能非常的少 但是第三方模块非常的多 |
| 类似于'游骑兵' |
| |
| |
| |
| tornado |
| 异步非阻塞框架 速度极快 甚至可以用于充当游戏服务器 |
| |
| |
| fastapi、sanic...... |
| |
| """ |
| 框架的核心逻辑几乎是一致的 我们在学习的时候只需要先学会一种 |
| 之后就可以触类旁通 但是需要强调的是:千万不用同时学习!!! |
| """ |
django
| |
| django3.X:默认支持异步功能 |
| django2.X:默认不支持异步 |
| django1.X:默认不支持异步 |
| ''' |
| 我们学习的时候 可以基于django1.11.X版本 与2.X功能几乎一致 |
| 3.X仅仅是多了一个功能(并且该功能目前还不完善 半成品!!!) |
| ''' |
| django1.11.X LTS 2018年发布 |
| django2.2.X LTS 2020年发布 |
| |
| |
| |
| django启动可能报错的原因 |
| 1.计算机名称不能含有中文 |
| 直接修改即可 |
| 2.不同版本的解释器可能会报错 |
| 找到报错信息的最后一行提示对应的代码 删除源文件逗号即可 |
| eg: 解释器推荐使用python3.6 几乎不会报错 |
| 解释器如果是高版本使用django1.11可能会报错 |
| 解释器如果是低版本使用django2、3也可以报错 |
| 3.项目中所有的文件名称最好使用英文 |
| 4.一个pycharm窗口尽量就是一个完整的项目 不要嵌套 |
| |
| |
| pip3 install django==1.11.11 |
| '''如果之前下载了其他版本不用管 自动替换!!!''' |
django基本使用
| |
| cmd窗口直接输入django-admin有反应就是成功了 |
| |
| 1.创建django项目 |
| django-admin startproject 项目名(mysite) |
| 2.启动django项目 |
| cd 项目名(mysite) |
| python3 manage.py runserver IP:PORT |
| 3.创建app应用 |
| python3 manage.py startapp 应用名(app01) |
| '''命令行无法自动创建模板文件夹 需要自己执行命令创建''' |
| |
| 1.new project |
| 选择django 填写应用即可 |
| '''pycharm默认会自动帮你创建模板文件夹 并提供创建一个app的功能''' |
| 2.创建更多的app |
| tools |
| run manage.py task 命令自动提示 |
| 3.启动项目 |
| 直接点击绿色箭头 |
| 还可以修改端口号 edit configurations |
应用app
| django本身类似于是一个空壳子 真正的功能是由里面的各个应用决定 |
| |
| django框架相当于是一所大学 应用相当于是大学里面的各个学院 |
| 大学其实是个壳子 负责提供环境 |
| 学院才是一个个真正具备特定功能的集合 |
| |
| eg: |
| 使用django写一个淘宝 |
| 淘宝里面有很多功能模块 |
| 我们应该先创建一个空的django项目然后根据功能的不同创建不同的应用 |
| django项目 |
| app01(user) |
| app02(order) |
| app03(goods) |
| app04(backend) |
主要文件介绍
| day50_1项目文件名 |
| day50_1同名文件夹 |
| |
| |
| manage.py |
| django入口文件 很多命令都需要该文件支持 |
| db.sqlite3 |
| django启动之后才会生成的文件 其实就是django自带的小型数据库 |
| templates文件夹 |
| 模板层 |
| app01应用文件夹 |
| |
| |
| |
| |
| |
| |
| """ |
| 创建应用之后 一定要去配置文件中注册才能生效 |
| 'app01.apps.App01Config' 完整语法 |
| 'app01' 简写语法 |
| """ |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY