不太清楚自己写到哪了,为了省事直接把笔记甩上去了,自用跟学链接:
说一下学完的感受:本来感觉没有多少收获,但是看完自己的笔记感觉还行吧,主要是了解了一下框架,自己写还是不会,但是这个flask还是很基础都不用了吧,继续学习的话建议学习Django也是Python的WEB框架就像java的springboot框架一样。
目录
不太清楚自己写到哪了,为了省事直接把笔记甩上去了,自用跟学链接:
[2.1 用户登录 知识点](#2.1 用户登录 知识点)
[1. flask蓝图](#1. flask蓝图)
[2. 前端input type类型:](#2. 前端input type类型:)
1.表结构

2.功能开发
2.1 用户登录 知识点
1. flask蓝图
(适用于比较大的文件,在一个py文件中写只适合写脚本)
app=....下边写视图函数
2. 前端input type类型:

3.MD5
本质 :它是哈希(指纹),不是加密。
特点 :不可逆 (算出了结果就变不回原文)、定长 (不管文件多大,结果都是 32 位字符)、极敏感(改一个字,结果大变样)。
现状 :不安全(防不住黑客碰撞),别存密码了,现在只用它校验文件有没有损坏。
import hashlib # 调用核心算法,生成sign签名 encrypt_string = ordered_string + "11111111111111" obj = hashlib.md5(encrypt_string.encode('utf-8')) sign = obj.hexdigest() return jsonify({"status": "True", "data": sign})
4.连接池
比喻 :就像公共自行车 / 网约车。
作用 :避免重复造轮子。创建连接(TCP 握手)很贵,连接池提前建好了一批连接放在池子里,谁要用直接拿,用完放回去,不用每次都重新建立连接。
好处 :快 (省去了握手时间)、稳(限制最大连接数,防止把数据库累垮)。
python
"""
# 集成mysql数据库连接池
"""
import hashlib
import pymysql
from dbutils.pooled_db import PooledDB
from flask import Flask, request, jsonify
# 声明一个flask变量(实例)
app = Flask(__name__)
POOL = PooledDB(
creator=pymysql, # 使用链接数据库的模块
maxconnections=10, # 连接池允许的最大连接数,0和None表示不限制连接数
mincached=2, # 初始化时,连接池中至少创建的空闲的链接,0表示不创建
maxcached=5, # 链接池中最多闲置的链接,0和None不限制
blocking=True, # 连接池中如果没有可用连接后,是否阻塞等待。True, 等待;False, 不等待然后报错
setsession=[], # 开始会话前执行的命令列表。如: ["set datestyle to ...", "set time zone ..."]
ping=0, # 判断当前链接是否可用
host='127.0.0.1', port=3306, user='root', passwd='123456', charset="utf8", db='flask01'
)
def fetch_one(sql, params):
# conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123456', charset="utf8", db='flask01')
conn = POOL.connection() # 去连接池里获取连接
cursor = conn.cursor()
cursor.execute(sql, params)
result = cursor.fetchone()
cursor.close()
conn.close() # 表示将此连接交还给连接池
return result
5.Cookie/Session/Redis
比喻 :会员卡(Cookie) 和 后台档案(Session)。
分工:
-
Cookie(存在你手里):存个身份证号(Session ID),每次去服务器都要带着。
-
Session(存在服务器):存你的详细信息(购物车、登录状态),服务器看到你手里的身份证号,就去查对应的档案。
核心逻辑 :Cookie 只是用来传 ID 的,真正的秘密都在服务器的 Session 里。
6.拦截器
在app函数中写

python
from flask import Flask, request, session, redirect
# 拦截器
def auth():
if request.path.startswith('/static'):
# 静态资源
return
if request.path == '/login':
# 不拦截
return
userinfo = session.get("userinfo")
if userinfo:
return
return redirect('/login')
def create_app():
app = Flask(__name__)
app.secret_key = '31131231334433333'
from .views import account
from .views import order
app.register_blueprint(account.ac)
app.register_blueprint(order.od)
app.before_request(auth) # 拦截器
return app
7.Redis:基于内存
Redis 连接配置文件
Windows 系统 :找到 Redis 安装目录,双击 redis-server.exe 启动 Redis 服务(或通过命令行 redis-server redis.windows.conf)。
Redis 是基于内存的键值对数据库,核心优势是「快」,支持多种数据结构和持久化。
你的项目中用 Redis List 实现了消息队列,这是 Redis 常用场景之一,核心命令是 lpush/rpop。
Redis 和 MySQL 是黄金搭档:MySQL 存持久化数据,Redis 存热点 / 临时数据,提升系统性能。
入门 Redis 只需掌握核心数据结构(String、List)和基本命令,即可满足大部分项目场景的需求。

常用的 String 命令:
| 数据结构 | 命令 | 作用说明 |
|---|---|---|
| List | lpush key value |
向列表 key 的头部插入一个 / 多个值(你的项目中用到的命令) |
| List | rpush key value |
向列表 key 的尾部插入一个 / 多个值 |
| List | rpop key |
从列表 key 的尾部取出并删除一个值 |
| List | lpop key |
从列表 key 的头部取出并删除一个值 |
| List | llen key |
获取列表 key 的长度(元素个数) |
| String | set key value |
设置一个字符串键值对(可添加过期时间:set key value ex 3600,有效期 1 小时) |
| String | get key |
获取 key 对应的 value 值 |
| String | incr key |
将 key 对应的数值加 1(计数器核心命令) |
| 通用 | exists key |
判断 key 是否存在(存在返回 1,不存在返回 0) |
| 通用 | del key |
删除指定的 key 及其对应数据 |
| 通用 | expire key seconds |
给 key 设置过期时间(单位:秒) |
2.2订单列表
3.1循环列表table>tr4>td5
<!--table>tr*4>td*5:4行5列,边框-->
<table border="1">
<tr>
<td>ID</td>
<td>URL</td>
<td>数量</td>
<td>状态</td>
<td>客户</td>
</tr>
{% for item in data_list %}
<tr>
<td>{{item.id}}</td>
<td>{{item.url}}</td>
<td>{{item.count}}</td>
<td>{{item.status}}</td>
<td>{{item.real_name}}</td>
</tr>
{% endfor %}
</table>
管理员:读取所有订单
用户:当前客户订单
3.2订单前端

表示内容平铺在整个页面
<div class="container-fluid">
表示居中
<div class="container">
要会查询圆角:
style="border-radius:0"
css样式组件网址:
表格样式:
<table class="table table-bordered"
表格 表单:
全局 CSS 样式 · Bootstrap v3 中文文档 | Bootstrap 中文网
进度按钮等:
组件 · Bootstrap v3 中文文档 | Bootstrap 中文网
2.3创建订单
python
# 订单创建
@od.route("/create", methods=["GET", "POST"]) # 实际访问路径:/order/create
def order_create():
if request.method == "GET":
return render_template("order_create.html")
url = request.form.get("url")
count = request.form.get("count")
# 写入数据库
user_info = session.get("user_info")
params = [url, count, user_info['id']]
order_id = db.insert("insert into `order` (url, count, user_id, status) values (%s, %s, %s, 1)",params)
print(order_id)
# 写入redis队列
cache.push_queue(order_id)
return redirect('/list')

-- 在数据库生成【待执行】
-- 放到redis队列【订单id】
-- 跳转订单列表
margin的用法:
.box { margin-top: 10px; /* 上边距 */ margin-right: 20px; /* 右边距 */ margin-bottom: 15px; /* 下边距 */ margin-left: 5px; /* 左边距 */ } margin: auto:水平居中 body, p, ul { margin: 0; /* 清除默认外边距 */ }
跳转功能a标签替换div

render_template:

模板继承:
模板文件,占位符

继承文件:
只需要在占位符中写入你不一样的部分即可,效果是一样的
{% extends 'layout.html' %} # 导入 {% block body %} <div class="panel panel-default"> <div class="panel-heading">新建订单</div> <div class="panel-body"> <form class="form-inline"> <div class="form-group"> <label class="sr-only" >Email address</label> <input type="text" class="form-control" placeholder="URL"> </div> <div class="form-group"> <label class="sr-only">数量</label> <input type="text" class="form-control" placeholder="数量"> </div> <button type="submit" class="btn btn-success">提交订单</button> </form> </div> </div> {% endblock %}
在模板中定义函数:

{{get_real_name()}} # 调用函数
2.4提交订单
查询的时候,只需要
result = cursor.fetchall() result = cursor.fetchone()
但是删除,修改,添加:
conn.commit()
redis见2.1.7
步骤:
-- redis中获取任务
-- 数据库获取并更新状态
-- 执行任务...,线程池
-- 执行完毕,更新订单状态
连接池:
''' redis 操作连接 ''' import redis POOL = redis.ConnectionPool(host='127.0.0.1', port=6379, max_connections=1000) def push_queue(value): conn = redis.Redis(connection_pool=POOL) # 队列名称DAY21_TASK_QUEUE键,值 conn.lpush("DAY21_TASK_QUEUE",value)
添加实现:
python
def insert(sql, params):
conn = POOL.connection() # 去连接池里获取连接
cursor = conn.cursor(cursor=cursors.DictCursor) # 数据库的cursors,返回数据的时候才会是一个字典
cursor.execute(sql, params)
conn.commit() # 提交
cursor.close()
conn.close() # 表示将此连接交还给连接池
return cursor.lastrowid # 获取新生成的id
2.5worker执行订单
-
监听redis队列
python
'''
worker运行在另一台服务器上
取到redis队列的数据送到worker去执行
redis 操作连接
'''
import redis
import pymysql
from pymysql import cursors
from dbutils.pooled_db import PooledDB
from concurrent.futures import ThreadPoolExecutor
"""
链接池
"""
DB_POOL = PooledDB(
creator=pymysql, # 使用链接数据库的模块
maxconnections=10, # 连接池允许的最大连接数,0和None表示不限制连接数
mincached=2, # 初始化时,链接池中至少创建的空闲的链接,0表示不创建
maxcached=5, # 链接池中最多闲置的链接,0和None不限制
blocking=True, # 连接池中如果没有可用连接后,是否阻塞等待。True, 等待;False, 不等待然后报错
setsession=[], # 开始会话前执行的命令列表。如: ["set datestyle to ...", "set time zone ..."]
ping=0, # 判断当前链接是否可用
host='127.0.0.1', port=3306, user='root', passwd='123456', charset="utf8", db='flask_order'
)
POOL = redis.ConnectionPool(host='127.0.0.1', port=6379, max_connections=1000)
# 获取一条数据
def fetch_one(sql, params):
conn = DB_POOL.connection() # 去连接池里获取连接
cursor = conn.cursor(cursor=cursors.DictCursor) # 数据库的cursors,返回数据的时候才会是一个字典
cursor.execute(sql, params)
result = cursor.fetchone()
cursor.close()
conn.close() # 表示将此连接交还给连接池
return result
def fetch_all(sql, params):
conn = DB_POOL.connection() # 去连接池里获取连接
cursor = conn.cursor(cursor=cursors.DictCursor) # 数据库的cursors,返回数据的时候才会是一个字典
cursor.execute(sql, params)
result = cursor.fetchall()
cursor.close()
conn.close() # 表示将此连接交还给连接池
return result
def pop_queue():
conn = redis.Redis(connection_pool=POOL)
# 队列名称DAY21_TASK_QUEUE键,值
data = conn.brpop("DAY21_TASK_QUEUE", timeout=10)
if not data:
return
return data[1].decode("utf-8")
def fetch_total_queue():
conn = redis.Redis(connection_pool=POOL)
total_count = conn.llen("DAY21_TASK_QUEUE")
def db_queue_init():
"""
1.去数据库获取待执行的订单id
2.去redis中获取待执行的订单id
3.找到数据库中有 且 redis队列中没有的所有订单id --> 重新放到redis的队列
:return:
"""
# 1.去数据库获取待执行的订单id
db_list = fetch_all("select id from `order` where status=1", [])
db_id_list = {item['id'] for item in db_list}
# 2.去redis中获取待执行的订单id
conn = redis.Redis(connection_pool=POOL)
total_count = conn.llen('DAY21_TASK_QUEUE')
cache_list = conn.lrange('DAY21_TASK_QUEUE', start=0, end=total_count) # 取的是
cache_int_list = {int(item.decode('utf-8')) for item in cache_list}
# 3.找到数据库中有且redis队列中没有的所有订单id --> 重新放到redis的队列 使用集合
need_push = db_id_list - cache_int_list
# 4.放入到redis队列
if need_push:
conn.lpush('DAY21_TASK_QUEUE', *need_push)
def get_order_object(order_id):
res = fetch_one("select * from `order` where id=%s", [order_id])
return res
def db_update(sql, params):
conn = DB_POOL.connection() # 去连接池里获取连接
cursor = conn.cursor(cursor=cursors.DictCursor) # 数据库的cursors,返回数据的时候才会是一个字典
cursor.execute(sql, params)
conn.commit() # 提交
cursor.close()
conn.close() # 表示将此连接交还给连接池
return cursor.lastrowid # 获取新生成的id
def update_order(order_id,status):
db_update("update `order` set status=%s where id=%s", [status, order_id])
def task(info_dict):
pass
def run():
# 1.初始化数据库未在队列中的订单
db_queue_init()
while True:
# 2.取队列中获取订单
order_id = pop_queue()
print(order_id)
if not order_id:
continue
# 3.查询订单是否存在,然后更新订单状态
order_dict = get_order_object(order_id)
if not order_dict:
continue
update_order(order_id, 2)
# 4.根据订单id去执行任务
print("执行订单任务", order_dict)
tread_pool = ThreadPoolExecutor(130)
for i in range(order_dict['count']):
tread_pool.submit(task, order_dict)
tread_pool.shutdown()
# 5.执行完成
update_order(order_id, 3)
if __name__ == '__main__':
run()
以下是之前的草稿里面的
11.接收任务并加入队列:
运行成功案例:
主要代码提示:
python
# 生成唯一任务ID(用uuid4)
tid = str(uuid.uuid4())
# 构造任务字典:包含任务ID和业务数据
task_dict = {'tid': tid, 'data': ordered_string}
REDIS_CONN_PARAMS = {
"host": '127.0.0.1',
# "password": '123456', # 我没有设置密码,默认Redis没有密码,也可以设置
"port": 6379,
"encoding": 'utf-8'
}
# 连接Redis
conn = redis.Redis(**REDIS_CONN_PARAMS)
# lpush:把任务字典转成JSON字符串,放入队列头部
conn.lpush("spider_task_list", json.dumps(task_dict))
# 给用户返回任务ID,提示正在处理
return jsonify({"status": True, 'data': tid, 'message': "正在处理中,预计1分钟完成"})

Redis下载路径: