本次内容解决的主要问题是Flask中运用SQLALchemy在进行蓝图模块化处理时遇到的问题,在用蓝图模块进行操作路由映射方法的时候,发现模块化的路由不能够直接进行实例化db操作数据库
本次程序的全部结构:
SQLALchemy的主要运用就是对象关系映射ORM模式操作数据库
1.建立mysql和app的连接
在config.py中加入几项数据库的配置:
# 创建数据库sqlalchemy工具链接
SQLALCHEMY_DATABASE_URI ="mysql+pymysql://root:Root123@127.0.0.1:3306/hj"
# 是否追踪数据库修改,一般不开启, 会影响性能
SQLALCHEMY_TRACK_MODIFICATIONS = False
# # 是否显示底层执行的SQL语句
SQLALCHEMY_ECHO = True
# 禁止自动提交数据处理
SQLALCHEMY_COMMIT_ON_TEARDOWN = False
2.完成app和数据的关联,并且生成一个可以操作app数据库的SQLALchemy的实例对象db
完整app/__init__.py代码:
from flask import Flask, current_app, url_for, request, redirect, render_template
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
"""上下文处理机制解决方法"""
ctx = app.app_context()
ctx.push()
"""------------------"""
app.config.from_object('config')
db = SQLAlchemy(app)
from app import models,views
注意:这里解决的一个位置的问题:RuntimeError: Working outside of application context
这里操作要获取得flask和对象app(即不启动服务器),但是获取不到app对象,原因是因为flask上下文机制,具体问题解释请查看https://blog.csdn.net/weixin_36672636/article/details/104612498/
3.创建数据表模块
#app/models.py
from app import db
#db是在app/__init__.py生成关联后的SQLALchemy实例
class User(db.Model):
# 定义表名
__tablename__ = 'users'
# 定义字段
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
name = db.Column(db.String(64))
password = db.Column(db.String(64))
phone = db.Column(db.String(64))
4.创建表db_create.py,表结构完成后执行db_create.py就可以完成表的创建
#app/db_create.py
from app import db, ctx
db.create_all()
ctx.pop()
5.业务流程操作数据库,并且使用蓝图对路由进行进行模块化处理
#app/user.py
from flask import Blueprint, render_template, request,current_app
from .models import User
from app import db
user = Blueprint('user', __name__)
@user.route('/login', methods=['GET', 'POST'])
def login():
if request.method =='GET':
return render_template('login.html')
user_name = request.form.get('name')
user_password = request.form.get('password')
user_phone = request.form.get('phone')
user = User()
user.name = user_name
user.password = user_password
user.phone = user_phone
db.session.add(user)
db.session.commit()
return render_template('success.html')
#app/admin.py
from flask import Blueprint, render_template, jsonify, request,current_app
from .common import random_num
from .redis_con import redis_store
from .models import User
admin = Blueprint('admin', __name__)
@admin.route('/')
def index():
if request.method == 'GET':
return render_template('index.html')
@admin.route('/valid_code')
def valid_vode():
# 获取数据
phone = request.args.get('phone')
print(phone)
try:
# 生成四位随机数字字母作为验证码
code = random_num()
# 将验证码保存到redis中,第一个参数是key,第二个参数是value,第三个参数表示60秒后过期
redis_store.set('{}'.format(phone), '{}'.format(code), 60)
# 这里用输出验证码来代替短信发送验证码
print(code)
return jsonify(status="成功", msg="验证码发送成功")
except Exception as e:
return jsonify(status='失败', msg="验证码发送失败")
@admin.route('/user_check')
def admin_check():
if request.method == 'GET':
users = User.query.all()
return render_template('user_check.html', users=users)
因为我个人的操作我这里添加了一个redis操作的部分内容,可以将@admin.route('/valid_code')此路由删除
#app/templates/login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登录</title>
<!-- 引入jquery -->
<script src="/static/js/jquery-3.6.5.js"></script>
</head>
<body>
<form action="/user/login" method="post">
用户名:<input type="text" name="name"><br>
密码:<input type="password" name="password" ><br>
手机号:<input type="text" name="phone" id="phone"><br>
验证码:<input type="text" name="valid_code" id="valid_code">
<input type="button" id="get_valid_code" value="获取验证码"><br>
<input type="submit" value="登录">
</form>
<script>
$(function(){
// 监听获取验证码按钮点击
$('#get_valid_code').click(function () {
var btn = $(this);
// 获取手机号
let phone = $('#phone').val();
// 有手机号才能获取验证码
if(phone){
// 使验证码按钮不可点击
btn.prop('disabled', true);
// 发送请求,后端模拟向对应手机号发送验证码
$.ajax({
// 请求方式
type: 'GET',
// 请求媒体类型
contentType: 'application/json;charset=UTF-8',
// 请求地址
url: 'http://127.0.0.1:5000/admin/valid_code?phone=' + phone,
// 请求成功
success: function (result) {
alert(result.msg)
},
// 请求失败,包含具体错误信息
error: function (e) {
alert(e.status);
alert(e.responseText);
}
})
// 倒计时秒数
var sec = 60;
// 创建定时器对象
var timer = setInterval(
function () {
// 秒数大于0,继续倒计时
if(sec>0) {
console.log($(this));
btn.val(String(sec) + '秒后再次发送');
sec--;
}else{
// 秒数小于0,重置秒数,使验证码按钮可以点击,并且清除定时器,使秒数不再倒计时
sec = 60;
btn.val('获取验证码');
btn.prop('disabled', false);
// 清除定时器
clearInterval(timer);
}
}, 1000);
}else{
alert("请输入手机号!!!")
}
})
})
</script>
</body>
</html>
这个HTML添加的js模块,去操作验证码的模块相应操作不需要可以将验证码部分代码和js相应代码删除:
验证码:<input type="text" name="valid_code" id="valid_code">
<input type="button" id="get_valid_code" value="获取验证码"><br>
#app/templates/user_check.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>UserCheck</title>
</head>
<body>
{% if users %}
<table border="1px">
<tr>
<th>UserName</th>
<th>UserPwd</th>
<th>UserPhone</th>
<th>DoSomeThing</th>
</tr>
{% for u in users %}
<tr>
<td>{{u.name}}</td>
<td>{{u.password}}</td>
<td>{{u.phone}}</td>
<td>修改</td>
</tr>
{% endfor %}
</table>
{% endif %}
</body>
</html>
#app/templates/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<a href="/user/login" >跳转页面</a>
</body>
</html>
此操作链接主要检验蓝图操作对路由的影响,譬如:http:127.0.0.1:5000/login -->http:127.0.0.1:5000/user/login, 路由会添加相对应的蓝图模块连接
#app/view.py
from app import app
from .admin import admin
from .user import user
#路由模块的划分
app.register_blueprint(admin,url_prefix='/admin')
app.register_blueprint(user, url_prefix='/user')
#app.py
from app import app
app.run()
from app(项目文件夹) import app(操作对象)主要依据的还是__init__.py文件中的获取操作对象app,内容本项目逻辑是在flask文件夹下可以添加多个项目,并且运行时可以选择性的的进行项目的添加和运行
本次例子运行只进行了部分的数据库操作,db.session.add(),user.query.all()其他数据操作还需要你们自己进行一些学习运用,这里主要记录的还是本人在使用蓝图中SQLALchemy的运行时候遇到的一些问题,redis连接部分简单,网上查看部分内容即可