手写简易web框架
import socket
server = socket.socket()
server.bind(('127.0.0.1', 8080))
server.listen(5)
spe_conn, address = server.accept() # 阻塞态
data = spe_conn.recv(1024)
data_str = data.decode('utf8')
current_path = data_str.split('\r\n')[0].split(' ')[1]
spe_conn.send(b'HTTP/1.1 200 ok\r\n\r\n')
if current_path == '/index':
with open(r'手写web前端页面.html', 'rb') as fr:
spe_conn.send(fr.read())
elif current_path == '/login':
spe_conn.send(b'login')
else:
spe_conn.send(b'404 error')
spe_conn.close()
基于wsgiref模块写web框架
ValueError
- [{'xxx': 'jason'}], not enough values to unpack(expect 2, got 1)
- ['xxx', 'jason'], too many values to unpack (expect 2)
- [('xxx', 'jason'), ]
views.py
存放函数, 这些函数被称为视图函数, 视图层
urls.py
存放路由后缀与视图函数的对应关系, 路由层
templates文件夹
存放html模板文件
动静态网页
- 静态页面, 数据在html页面上是写死的, 不会发生任何改变
- 数据是实时获取的, eg: 1. 后端代码动态获取当前时间; 2. 数据是从数据库中查询出来的
- 后端数据-->html页面-->前端-->浏览器渲染
jinja2模板语法
- 专门用来出来后端数据与html页面的交互
- 模板语法: 能够在html页面上, 用类似于python的语法操作后端传递过来的数据
def get_user_dic(env):
from jinja2 import Template
user_dic = {'user_name': 'jason', 'hobby': ['read', 'book', 'run']}
with open(r'templates/get_user_dic.html', 'r', encoding='utf8') as fr:
data = fr.read() # 在内存中读取HTML模板
temp = Template(data) # 得到temp对象
res = temp.render(userDic=user_dic) # 根据HTML模板中的模板语法, 将user_dic渲染到HTML模板中, 在内存中生成一个完整的HTML文件(即res)
# print(res)
return res
'''
res对应整个html页面在内存中渲染后的结果
模板语法部分对应结果:
<p>{'user_name': 'jason', 'hobby': ['read', 'book', 'run']}</p>
<p>jason</p>
<p>['read', 'book', 'run']</p>
<p>read</p>
<p>book</p>
<p>run</p>
'''
<!--模板语法-->
<p>{{userDic}}</p>
<p>{{userDic.user_name}}</p>
<p>{{userDic['hobby']}}</p>
<p>{{userDic.get('hobby').0}}</p>
<p>{{userDic.get('hobby').1}}</p>
<p>{{userDic.get('hobby').2}}</p>
基于jinjia2数据库中的数据
-
pymysql.connect-->Connect-->
__init__
-
模板的渲染: 将后端处理好的数据, 在内存中读取HTML模板, 并通过jinjia2模板语法生成一个完整的HTML文件的过程
-
模板的渲染是在后端完成的, 与前端无关
-
pymsql复习
import pymysql client = pymysql.connect( host='127.0.0.1', port=3306, user='root', password='Cql123456', db='django', charset='utf8', autocommit=True ) cursor = client.cursor(pymysql.cursors.DictCursor) # 将查询出的数据组织成一个字典 sql = "select id, username, password from user_info" # 当数据量特别大时, *会降低查询效率 affect_rows = cursor.execute(sql) # sql注入: 利用mysql注释语法钻漏洞, 关键数据交给execute拼接 user_lt = cursor.fetchall()
python三大主流web框架
web框架请求流程图
python三大主流web框架
django:
- 优点: 大而全, 自带的组件和功能非常多, 类似于航空母舰
- 缺点: 写小项目是可能会大材小用
- socket部分用的wsgiref, 路由匹配和模板语法自己写的
flask:
- 优点: 小而精, 更多依赖于第三方组件, 类似于游骑兵
- 缺点: 受限于第三方模块的影响比较大
- 如果将flask所有第三方模块加起来, 能够直接盖过django
- socket部分用的werkzeug, 路由匹配自己写的, 模板语法用的jinjia2
tornado:
- 异步非阻塞, 通过回调函数处理异步任务结果, tornado甚至可以用来开发游戏服务器
- socket, 路由匹配和模板语法都是自己写的
django安装
安装django注意事项
- 计算机名称不能有中文
- python解释器不要使用3.7, 推荐版本3.4~3.6
- 一个pycharm窗口, 只跑一个django项目
- django版本以1.11.11为主
- 验证django是否安装成功: 在cmd中执行django-admin, 看是否有反应
命令行创建django项目
-
创建django项目:
django-admin startproject 项目名
-
启动django项目:
manage.py runserver127.0.0.1:8080
-
app: django是一个以开放app为主要功能的web框架
一个django项目类似于一所大学, 而app类似于大学里的学院
可以根据功能的不同开放多个app, 一个app对应一个具体的功能模块
创建app:
python manage.py startapp app名
-
不会自动创建templates文件夹, 创建后手动将templates文件夹路径添加到settings.py中
settings-->TEMPLATES-->'DIRS': [os.path.join(BASE_DIR, 'templates')]
pycharm创建django项目
1.创建的app需要在django配置文件中注册才能生效: 'INSTALLED_APPS = [..., app02.apps.App02Config']
通过反射找到所创建的app
2.一定要确保同一个端口同一时间只能启一个django项目
3.更改使用的数据库, settings-->DATABASES
django文件功能
django项目名
- 项目同名的文件夹
- settings.py: 配置文件
- urls.py: 路由与视图函数对应关系
- manage.py: django的入口文件
- 应用名文件夹
- migrations文件夹: 所有数据库相关的操作记录
- admin.py: django中admin后台管理
- apps.py: 注册app使用
- models.py: 存放数据库相关的模型表类
- test.py: 测试文件
- views.py: 处理业务逻辑的视图函数
django小白必会三板斧
-
HttpResponse: 返回字符串
def index(request): # 参数request <==> env, 必须传 return HttpResponse('一脸懵逼')
-
render: 返回HTML文件, 可以给HTML文件传值
def login(request): user_dic = {'username': 'jason', 'password': '123'} return render(request, 'login.html', {'userDic': user_dic})
-
redirect: 重定向, 1. 直接写本网站的路径后缀; 2. 写其他网站全路径
def home(request): return redirect('/login') # return redirect('https://www.baidu.com')
-
重启机制: 内有检测机制, 实时检测所有文件的变化, 有时会产生代码还没写完就自动重启报错的情况, 不用管