[已解决][提问帖]使用Flask-SQLAlchemy的SQLAlchemy插件连接Mysql,在Flask Run后页面出现未定义名称错误

因为书本教程中木有连接外部数据库的案例,都是在网上找的教程拼拼凑凑,反正今天出现的问题跟昨天不一样了
1.求问:如何解决这个问题
2.求问:为什么这样写法会错误?

app.config["SQLALCHEMY_DATABASE_URI"] = DB_URI
DB_URI = "{}+{}://{}:{}@{}:{}/{}?charset=utf8mb4".format(DIALECT, DRIVER, USERNAME, PASSWORD, HOST, PORT, DATABASE)

我先不用这样的写法:

SQLALCHEMY_DATABASE_URI = "{}+{}://{}:{}@{}:{}/{}?charset=utf8mb4".format(DIALECT, DRIVER, USERNAME, PASSWORD, HOST, PORT, DATABASE)

3.求问:正确的代码
4.@greyli

数据库配置文件(db_config.py)

# -*- coding: utf-8 -*-

DIALECT = 'mysql'
DRIVER = 'pymysql'
USERNAME = 'root'
PASSWORD = '123456'
HOST = '192.168.121.128'
PORT = '3306'
DATABASE = 'tcgamelist'
app.config["SQLALCHEMY_DATABASE_URI"] = DB_URI

DB_URI = "{}+{}://{}:{}@{}:{}/{}?charset=utf8mb4".format(DIALECT, DRIVER, USERNAME, PASSWORD, HOST, PORT, DATABASE)
SQLALCHEMY_TRACK_MODIFICATIONS = False

主程序文件(watchlistapp.py)

# -*- coding: utf-8 -*-

from flask import Flask, url_for, render_template
from flask_sqlalchemy import SQLAlchemy

import db_config

app = Flask(__name__)
app.config.from_object(db_config)
db = SQLAlchemy(app)

class Moiveusers(db.Model):# 表名将会是 user(自动生成,小写处理)
    __tablename__ = 'movieusers'# 自定义表名字
    id = db.Column(db.Integer, primary_key=True)# 主键
    username = db.Column(db.String(20), nullable=False)# 名字

class Movielist(db.Model):# 表名将会是 movie
    __tablename__ = 'movielist'# 自定义表名字
    id = db.Column(db.Integer, primary_key=True)# 主键
    title = db.Column(db.String(60))# 电影标题
    year = db.Column(db.String(4))# 电影年份

db.create_all()

name = 'Tc_Dhl'
movies = [
    {'title': '电影1', 'year': '1991'},
    {'title': '电影2', 'year': '1992'},
    {'title': '电影3', 'year': '1993'},
    {'title': '电影4', 'year': '1994'},
    {'title': '电影5', 'year': '1995'},
    {'title': '电影6', 'year': '1996'},
    {'title': '电影7', 'year': '1997'},
    {'title': '电影8', 'year': '1998'},
]

@app.route('/')
def hello():
    return 'Hello'

@app.route('/user/<name>')
def t123(name):
    return '访问用户名: %s' % name

@app.route('/test')
def test_url_for():
    # 下面是一些调用示例(请在命令行窗口查看输出的 URL):
    print(url_for('hello'))  # 输出:/
    # 注意下面两个调用是如何生成包含 URL 变量的 URL 的
    print(url_for('t123', name='greyli'))  # 输出:/user/greyli
    print(url_for('t123', name='peter'))  # 输出:/user/peter
    print(url_for('test_url_for'))  # 输出:/test
    # 下面这个调用传入了多余的关键字参数,它们会被作为查询字符串附加到 URL 后面。
    print(url_for('test_url_for', num=2))  # 输出:/test?num=2
    return 'Test page'

@app.route('/movie')
def movie():
    return render_template('movie.html', name=name, movies=movies)

Flask Run后Terminal输出日志

(.venv-watchlist) E:\A-WorkDatas\IDE_VsCode_B_后端项目源码\python学习\watchlist>flask run
 * Serving Flask app "watchlistapp" (lazy loading)
 * Environment: development
 * Debug mode: on
 * Restarting with windowsapi reloader
 * Debugger is active!
 * Debugger PIN: 207-246-360
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)

打开页面后报错的样子

你在引用 DB_URI 变量的时候它还没有创建(代码从上往下执行)。试试把 DB_URI 放到前一行:

DB_URI = "{}+{}://{}:{}@{}:{}/{}?charset=utf8mb4".format(DIALECT, DRIVER, USERNAME, PASSWORD, HOST, PORT, DATABASE)
app.config["SQLALCHEMY_DATABASE_URI"] = DB_URI

报错很明显了,app 变量没导入……

为什么不用下面的写法?

SQLALCHEMY_DATABASE_URI = "{}+{}://{}:{}@{}:{}/{}?charset=utf8mb4".format(DIALECT, DRIVER, USERNAME, PASSWORD, HOST, PORT, DATABASE)

这个写法 运行后确实是没问题…
但老哥你看这篇帖子点击查看
他里面有写app变量,为啥他这种写法不会有错
我纠结这种写法呢,是觉得这样子代码看起来会比较规整一点

你要使用其他模块里的变量,就要先 config_db.py 导入:

from watchlistapp import app

哇…

循环依赖了(两个模块互相导入)。你没必要这么写,就直接定义就好:

SQLALCHEMY_DATABASE_URI = "{}+{}://{}:{}@{}:{}/{}?charset=utf8mb4".format(DIALECT, DRIVER, USERNAME, PASSWORD, HOST, PORT, DATABASE)
2 个赞

嗯嗯好的

我后来后试了一下,改成这样也能运行成功
我改成这样,主要是觉得 代码行的长度会看起来正好合适哈哈

SQLALCHEMY_DATABASE_URI = DB_URI

DB_URI = "{}+{}://{}:{}@{}:{}/{}?charset=utf8mb4".format(DIALECT, DRIVER, USERNAME, PASSWORD, HOST, PORT, DATABASE)

奇怪的写法。

使用一个变量(作为右值)之前,一般是要先定义一个变量(作为左值)。

所以要是下面这样写我还能接受。。。。

DB_URI = "{}+{}://{}:{}@{}:{}/{}?charset=utf8mb4".format(DIALECT, DRIVER, USERNAME, PASSWORD, HOST, PORT, DATABASE)
SQLALCHEMY_DATABASE_URI = DB_URI

对对对 是这样的哈哈,我把顺序弄反了