flask_蓝图
Flask蓝图是Flask框架中用于组织大型应用程序的一种方式。
蓝图允许你将应用程序分解为多个组件,每个组件可以有自己的路由,视图函数、模板和静态文件。
这种模块化的设计使得代码更加清晰、易用维护和扩展
主要用途
-
模块化:将应用程序的不同部分拆分为独立的蓝图。
-
可重用性:创建可重用的应用组件。
-
组织结构:更好地组织大型应用程序的代码结构。
基本概念 -
蓝图对象:使用 Blueprint 类创建蓝图对象。
-
注册蓝图:将蓝图对象注册到 Flask 应用实例中。
-
路由:在蓝图中定义路由和视图函数。
-
模板和静态文件:蓝图可以有自己的模板和静态文件目录。
创建蓝图
首先,创建一个蓝图对象。
user.py
# -*- coding: utf-8 -*-
# 用户模块
from flask import Flask,jsonify,request,Blueprint
import re
# 导入类试图
from flask.views import MethodView
# 导入数据库
from database import db,r
from utils import SendEmail,get_code,save_code,is_vaild_email,make_password
from sqlalchemy import text
# 实例化蓝图对象
user_view = Blueprint('user_view',__name__)
# 用户模块类试图
class SendCodeApi(MethodView):
# get发送
def get(self):
# 接受邮箱参数
email = request.args.get('email')
# 非空验证
if not email:
return jsonify({'code':101,'msg':'Data is not empty'})
# 判断是否是邮箱
if not is_vaild_email(email):
return jsonify({'code':102,'msg':'Data not is_vaild_email'})
# 生成随机验证码
code = get_code()
# 调用发送邮件方法
send = SendEmail()
send.send_email(email,'注册验证码',str(code))
# 保存随机验证码
res = save_code(email,lifetime=180,code=code)
if not res:
return jsonify({'code':103,'msg':'code_error'})
return jsonify({'code':200,'msg':'code_success'})
def post(self):
"""
:return:
"""
data = request.get_json()
email = data.get('email')
code = data.get('code')
password = data.get('password')
# 输入值不为空
if not email or not code:
return jsonify({'code':101,'msg':'Data is not empty'})
# 判断是否是邮箱
if not is_vaild_email(email):
return jsonify({'code':102,'msg':'Data not is_vaild_email'})
# redis 获取验证码
redis_code = r.get(email)
if not redis_code:
return jsonify({'code':103,'msg':'code_exp,please agin'})
# 比对验证码
if str(code) != str(redis_code):
return jsonify({'code':104,'msg':'The input on both sides is inconsistent'})
_sql = "insert into `user` (`email`,`password`) values('{}','{}')".format(email,make_password(password))
print(_sql)
try:
db.session.execute(text(_sql))
db.session.commit()
db.session.close()
return jsonify({'code':200,'msg':'success'})
except Exception as e:
db.session.rollback()
return jsonify({'code':105,'msg':str(e)})
except InterruptedError as e:
db.session.rollback()
return jsonify({'code':106,'msg':str(e)})
class UserApi(MethodView):
# 登录
"""
判断是否空
邮箱是否存在
密码是否相同
"""
def post(self):
data = request.get_json()
email = data.get('email')
password = data.get('password')
_sql = "select `email`,`password` from `user` where email='{}'".format(email)
res = db.session.execute(text(_sql)).fetchone()
if res:
if make_password(password) == res[1]:
return jsonify({'code':200,'msg':'success login'})
else:
return jsonify({'code':101,'msg':'password error'})
else:
return jsonify({'code':102,'msg':'email error'})
# 类试图添加路由
# 注册
user_view.add_url_rule('/sendcode/',view_func=SendCodeApi.as_view('sendcode'))
# 登录
user_view.add_url_rule('/userapi/',view_func=UserApi.as_view('userapi'))
app.py
# encoding: utf-8
import json
from flask import Flask, jsonify, request
from flask_cors import CORS
from database import db,r
from flask.views import MethodView
from sqlalchemy import text
from config import *
# 导入蓝图模块
from user import user_view
# 实例化flask对象
app = Flask(__name__)
# 配置转码
app.config['JSON_AS_ASCII'] = False
# 配置跨越
CORS(app, cors_allowed_origins="*")
# 配置mysql数据库
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://{}:{}@{}:{}/{}'.format(mysql_user,mysql_password,mysql_host,mysql_port,mysql_db)
# 自动提交sql请求
app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = True
# 注册蓝图
app.register_blueprint(user_view)
# 初始化操作
db.init_app(app)
if __name__ == '__main__':
app.run(debug=True, host='0.0.0.0', port=5000)
utils.py
# -*- coding: utf-8 -*-
# 工具库
import random
import smtplib
# 导入邮件文本
from email.mime.text import MIMEText
import datetime
# 导入邮件分类
from email.mime.multipart import MIMEMultipart
from database import r
# 正则
import re
# 导入hashlib
import hashlib
# 邮件发送类
class SendEmail:
# 初始化方法
def __init__(self):
# 初始化邮箱数据
# 发送者的邮箱
self._user = 'luckyletop@163.com'
# 发送者邮箱的授权码
self._pwd = 'xxxxxx'
# 发送方法
def send_email(self, _touser, _title, _content):
# 构建邮件体
msg = MIMEMultipart()
# 邮件标题
msg['Subject'] = _title
# 发件人
msg['From'] = self._user
# 收件人
msg['To'] = _touser
# 构建内容
part = MIMEText("验证码:{}".format(_content),'html','utf-8')
msg.attach(part)
# 发送逻辑
# 建立连接对象
s = smtplib.SMTP_SSL('smtp.163.com', 465)
# 登录邮箱
s.login(self._user, self._pwd) # 修改这里
# 发送邮件
s.sendmail(self._user, _touser, msg.as_string())
# 关闭链接
s.close()
# 验证码封装随机六位数
# 列表转换字符串 ''.join(list)
# 字符串转列表 ''.split()
def get_code(abc=True,length=4):
if abc:
base_str = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
else:
base_str = '1234567890'
# 生成逻辑
return ''.join([random.choice(base_str) for _ in range(length)])
# 随机码的存储
def save_code(email,lifetime,code):
# 原子操作,确保原子性 都执行或都不执行
# 原子性保存验证码
return r.setex(email,lifetime,code)
# 正则验证邮箱
def is_vaild_email(email):
# 正则判断是否是合法邮箱
ex_email = re.compile(r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$')
# 匹配正则
res = ex_email.match(email)
return res
# 密码加密
def make_password(password, salt='luckyletop'):
"""
哈希算法是一种将任意长度的数据映射为固定长度的字符串
md5:不可逆
"""
# 生成md5对象
md5 = hashlib.md5()
# 转码
password_str = str(password+salt).encode(encoding='utf-8')
# 加密操作
md5.update(password_str)
return md5.hexdigest()
if __name__ == '__main__':
# 随机验证码
code = get_code()
# 实例化 对象
# send = SendEmail()
# send.send_email('luckyletop@163.com','测试邮件标题',code)
# save_code('luckyletop@163.com',lifetime=120,code=code)
# print(is_vaild_email('luckyletop@163.com'))
# print(make_password('123456'))