目录
推导流程
纯手撸web框架
-
web框架的本质
1.连接前端于数据库的中间介质 2.socket服务端
-
手写web框架
1.编写socket服务端代码 2.浏览器访问响应无效>>>:HTTP协议 HTTP协议: 超文本传输协议:规定了浏览器与服务器之间数据交互的格式 HTTP协议的四大特性: 1.基于请求响应 -- 浏览器给服务端发起请求,服务端收到后做出回应 2.基于TCP、IP协议作用于应用层之上的协议 3.无状态 -- 不保存用户端的登录状态,见你千百遍我都当你如初见 4.无(短)连接 -- 一次请求响应后即断开连接 HTTP协议的数据传输格式: 1.请求数据格式: 请求首行(请求方法...) 请求头(一大堆K:V键值对) \r\n ---换行 请求体(并不是所有的请求方法都有 主要用来携带敏感性数据) 2.响应数据格式: 响应首行(响应状态码...) 响应头(一大堆k:v键值对) \r\n ---换行 响应体(展示给用户的数据) 3.根据网址后缀的不同获取不同的页面内容 4.想办法获取到用户输入的后缀>>>:请求数据 5.请求首行 GET /login HTTP/1.1 GET:朝服务端索要数据 POST:朝服务端提交数据 6.从请求数据格式中筛选出用户输入的网址后缀(从字符串中截取出来需要得内容) target_url = data.decode('utf8').split(' ')[1] 注意: """ 1.socket代码过于重复 2.针对请求数据处理繁琐 3.后缀匹配逻辑过于LowB """
代码: import socket server = socket.socket() # TCP UDP server.bind(('127.0.0.1', 8080)) # IP PORT server.listen(5) # 半连接池 while True: sock, address = server.accept() # 等待连接 data = sock.recv(1024) # 字节(bytes) # print(data.decode('utf8')) # 解码打印 sock.send(b'HTTP/1.1 200 OK\r\n\r\n') data_str = data.decode('utf8') # 先转换成字符串 target_url = data_str.split(' ')[1] # 按照空格切割字符串并取索引1对应的数据 # print(target_url) # /index /login /reg if target_url == '/index': # sock.send(b'index page') with open(r'myhtml01.html','rb') as f: sock.send(f.read()) elif target_url == '/login': sock.send(b'login page') else: sock.send(b'home page!')
基于wsgiref模块
wsgiref是一种内置模块,它是很多web框架底层使用的模块
作用:封装了socket代码
处理了请求数据
这时使用wsgiref模块可以:
1.固定代码启动服务端
2.查看处理之后的request大字典
3.根据不同的网址后缀返回不同的内容>>>:它是一个字典键值对,研究大字典键值对
4.立刻解决上述纯手撸的前两个问题
5.针对最后一个问题代码如何优化
代码:
from wsgiref.simple_server import make_server
def run(request, response):
"""
:param request: 请求相关数据
:param response: 响应相关数据
:return: 返回给客户端的真实数据
"""
response('200 OK', []) # 固定格式 不用管它
# print(request) 是一个处理之后的大字典
path_info = request.get('PATH_INFO')
if path_info == '/index':
return [b'index']
elif path_info == '/login':
return [b'login']
return [b'hello wsgiref module']
if __name__ == '__main__':
server = make_server('127.0.0.1', 8080, run) # 实时监听127.0.0.1:8080 一旦有请求过来自动给第三个参数加括号并传参数调用
server.serve_forever() # 启动服务端
代码封装优化
作用:
1.网址后缀的匹配问题
2.每个后缀匹配成功后执行的代码有多有少
面条版 函数版 模块版
3.将分支的代码封装成一个个函数
4.将网址后缀与函数名做对应关系
5.获取网址后缀循环匹配
6.如果想新增功能只需要先写函数再添加一个对应关系即可
7.根据不同的功能拆分成不同的py文件
views.py 存储核心业务逻辑(功能函数)
urls.py 存储网址后缀与函数名对应关系
templates目录 存储html页面文件
8.为了使函数体代码中业务逻辑有更多的数据可用
将request大字典转手传给这个函数(可用不用但是不能没有)
views代码:
def index_func(request):
return 'index function'
def login_func(request):
with open(r'templates/myhtml02.html', 'r', encoding='utf8') as f:
return f.read()
# return 'login function'
def reg_func(request):
return 'reg function'
def error_func(request):
return '404 Not Found'
def logout_func(request):
return 'logout function'
urls代码:
from views import *
urls = [
('/index', index_func),
('/login', login_func),
('/reg', reg_func),
('/logout', logout_func),
('/get_time', get_time_func),
('/get_dict', get_dict_func),
('/get_user', get_user_func)
]
动静态网页
动态网页
页面数据来源于后端
静态网页
页面数据直接写死
1.访问某个网址后缀 后端代码获取当前时间 并将该时间传到html文件上再返回给浏览器展示给用户看
读取html内容(字符串类型) 然后利用字符串替换 最后再返回给浏览器
2.将字典传递给页面内容 并且在页面上还可以通过类似于后端的操作方式操作该数据
模板语法>>>:jinja2模块
jinja2模块
pip3 install jinja2
from jinja2 import Template
def get_dict_func(request):
user_dict = {'name': 'jason', 'age': 18, 'person_list': ['阿珍', '阿强', '阿香', '阿红']}
with open(r'templates/get_dict_page.html', 'r', encoding='utf8') as f:
data = f.read()
temp_obj = Template(data) # 将页面数据交给模板处理
res = temp_obj.render({'d1': user_dict}) # 给页面传了一个 变量名是d1值是字典数据的数据
return res
<p>{{ d1 }}</p>
<p>{{ d1.name }}</p>
<p>{{ d1['age'] }}</p>
<p>{{ d1.get('person_list') }}</p>
jinja2能够让我们在html文件内使用类似于后端的语法来操作各种数据类型
jinja2模板语法:
{{···}}
{%···%}
前端、后端、数据库三者联动
关系:前端浏览器访问get_user
后端连接数据库查询user表中所有的数据 然后传递到某个html页面 弄好样式 最后发送给浏览器展示
{% for user_dict in user_data_list %}
<tr>
<td>{{ user_dict.id }}</td>
<td>{{ user_dict.name }}</td>
<td>{{ user_dict.age }}</td>
</tr>
{% endfor %}
python主流web框架
"""
作为小白的你 初学阶段不要混着学 很容易走火入魔
"""
1.django
大而全 自身自带的功能组件非常的多 类似于航空母舰
2.flask
小而精 自身自带的功能组件非常的少 类似于游骑兵
几乎所有的功能都需要依赖于第三方模块
3.tornado
异步非阻塞 速度极快效率极高甚至可以充当游戏服务端
ps:sanic、fastapi...
三大主流web框架特点
django:
socket部分用的是别人的 wsgiref模块
路由与视图函数对应关系(路由匹配)用的是自己的
模版语法用的是自己的(没有jinja2好用 但是也很方便)
flask:
socket部分用的是别人的 werkzeug(内部还是wsgiref模块)
路由与视图函数对应关系(路由匹配)自己写的
模版语法用的别人的(jinja2)
tornado:
socket部分,路由与视图函数对应关系(路由匹配),模版语法都是自己写的
django简介
-
版本问题
django1.X:同步 1.11 LTS稳定版 django2.X:同步 2.2 LTS稳定版 django3.X:支持异步 3.2 LTS稳定版 django4.X:支持异步 4.2 LTS稳定版 ps:版本之间的差异其实不大 主要是添加了额外的功能
-
注意事项
1.django项目中所有的文件名目录名不要出现中文 2.计算机名称尽量也不要出现中文 3.一个pycharn尽量就是一个完整的项目(不要嵌套 不要叠加) 4.不同版本的python解释器与不同版本的django可能会出现小问题
django基本使用
1.下载 pip3 install django 默认最新版 pip3 install django==版本号 指定版本 pip3 install django==2.2.22 是我们需要下载的 pip下载模块会自动解决依赖问题(会把关联需要用到的模块一起下了) 2.验证下载是否成功 django-admin 3.常见命令 3.1 创建django项目 django-admin startproject 项目名 3.2 启动django项目 cd 项目名 python38 manage.py runserver ip:port 4.pycharm自动创建django项目 在pycharm下载完成时会自动创建templates文件夹 但是配置文件中可能会报错 加上[os.path.join(BASE_DIR,'templates'), ]
django app的概念
-
django类似于是一所大学 app类似于大学里面的各个学院
-
django里面的app类似于某个具体的功能模块
user app 所有用户相关的都写在user app下 goods app 所有商品相关的都写在goods app下
-
命令行创建应用
python38 manage.py startapp 应用名
-
pycharm创建应用
新建django项目可以默认创建一个 并且自动注册
"""
创建的app一定要去settings.py中注册
INSTALLED_APPS = [
'app01.apps.App01Config', 全写
'app01', 简写
]
"""
django主要目录结构
-
django项目目录名
django项目同名目录 settings.py 配置文件 urls.py 存储网址后缀与函数名对应关系(不严谨) wsgi.py wsgiref网关文件 db.sqlite3文件 django自带的小型数据库(项目启动之后才会出现) manage.py 入口文件(命令提供)
-
应用目录
migrations目录 存储数据库相关记录 admin.py django内置的admin后台管理功能 apps.py 注册app相关 models.py 与数据库打交道的(非常重要) tests.py 测试文件 views.py 存储功能函数(不严谨) templates目录 存储html文件(命令行不会自动创建而pycharm会自动创建) 配置文件中还需要配置路径 [os.path.join(BASE_DIR,'templates'),]
-
重要名词讲解
urls.py 路由层 views.py 视图层 models.py 模型层 templates 模版层 """ 网址后缀 路由 函数 视图函数 类 视图类 """
django小白必会三板斧
导入的模块
from django.shortcuts import render,HttpResponse,redirect
HttpResponse 返回字符串类型的数据
render 返回html页面并且支持传值
redirect 重定向
标签:web,模块,app,py,django,user,func
From: https://www.cnblogs.com/wxlxl/p/16967095.html