Python 如何围绕现有数据库构建flask应用程序?
我已经有了一个现有的数据库,在Python 如何围绕现有数据库构建flask应用程序?,python,mysql,sqlalchemy,flask,flask-sqlalchemy,Python,Mysql,Sqlalchemy,Flask,Flask Sqlalchemy,我已经有了一个现有的数据库,在MySQL中有很多表和很多数据。我打算创建一个Flask应用程序,并使用sqlalchemy。现在我在irc上发问,在谷歌上四处看看,并尝试了以下想法: 首先我使用我的DB生成模型。但后来我有点困惑,又看了看。我发现了 这看起来是一个优雅的解决方案 因此,第二次,我根据那里的解决方案重写了我的models.py,现在我更加困惑了。我正在寻找最好的方法来构建这个flask应用程序以及已经存在的DB 我查阅了flask文档,但是对于一个已经存在db的项目,我并没有得到任
MySQL
中有很多表和很多数据。我打算创建一个Flask
应用程序,并使用sqlalchemy。现在我在irc上发问,在谷歌上四处看看,并尝试了以下想法:
首先我使用我的DB
生成模型。但后来我有点困惑,又看了看。我发现了
这看起来是一个优雅的解决方案
因此,第二次,我根据那里的解决方案重写了我的models.py
,现在我更加困惑了。我正在寻找最好的方法来构建这个flask应用程序以及已经存在的DB
我查阅了flask文档,但是对于一个已经存在db的项目,我并没有得到任何帮助。有很多好东西可以从头开始创建,创建数据库等等。但我真的很困惑
请注意,这是我第一天使用
Flask
,但我有使用Django
的经验,因此基本概念不是障碍。在为这个用例选择最佳方法时,我需要一些指导。如能详细解释,将不胜感激。通过详细说明,我绝对不希望有人编写所有的代码并用勺子喂我,但这足以让我开始,那就是通过sqlalchemy
将此db无缝集成到flask
。注意我的数据库在MySQL中,我想说你的问题与flask没有任何关系。例如,模板、路由、视图或登录装饰器并没有问题
你挣扎的地方是炼金术
所以我的建议是暂时忽略烧瓶,先习惯炼金术。您需要习惯现有数据库以及如何从SQLAlchemy访问它。使用一些MySQL文档工具来解决这个问题。开始时是这样的(请注意,它与烧瓶问所有……还没有任何关系):
在“engine=
”行中,您需要提供MySQL数据库的路径,以便SQLAlchemy找到它。在我的例子中,我使用了一个预先存在的sqlite3数据库
在“classusers(Base)
”行中,您需要使用MySQL数据库中的一个现有表。我知道我的sqlite3数据库有一个名为“users”的表
在这一点之后,SQLalchemy知道如何连接到MySQL数据库,并且知道其中一个表。您现在需要添加您所关心的所有其他表。最后,您需要指定与SQLalchemy的关系。这里我指的是一对一、一对多、多对多、亲子关系等等。SQLAlchemy网站包含一个关于这方面的相当长的部分
在“行后面,如果
”后面是一些测试代码。如果我不导入python脚本,而是运行。在这里,您可以看到我创建了一个DB会话,这是一个非常简单的查询
我建议您首先阅读SQLAlchemy文档的重要部分,例如描述性表定义、关系模型和如何查询。一旦知道了这一点,就可以将我的示例的最后一部分更改为控制器(例如,使用Python的
yield
方法),并编写一个使用该控制器的视图 我最近经历了同样的事情,还有一个额外的挑战是跨两个数据库链接模型
我使用了,我所要做的就是以与数据库表相同的方式定义模型。我发现困难的是弄清楚我的项目结构应该是什么样子
我的项目是一个Restful API,这就是我最终得到的:
conf/
__init__.py
local.py
dev.py
stage.py
live.py
deploy/
#nginx, uwsgi config, etc
middleware/
authentication.py
app_name/
blueprints/
__init__.py
model_name.py #routes for model_name
...
models/
__init.py
model_name.py
__init__.py
database.py
tests/
unit/
test_etc.py
...
run.py
值得注意的文件:
conf/xxx.py
from flask.ext.sqlalchemy import SQLAlchemy
db = SQLAlchemy()
from services.database import db
class Bar(db.Model):
__tablename__ = 'your_MySQL_table_name'
id = db.Column('YourMySQLColumnName', db.Integer, primary_key=True)
name = db.Column('WhateverName', db.String(100))
foo = db.Column(db.ForeignKey('another_MySQLTableName.id'))
class Foo(db.Model):
__tablename__ = 'another_MySQLTableName'
id = db.Column('FooId', db.Integer, primary_key=True)
...
#! /usr/bin/env python
from app_name import create_app
app = create_app(env='local')
if __name__ == '__main__':
app.run()
这就是我们告诉Flask SQLAlchemy连接到什么的方式,另外您可以在这里放置任何其他配置项(如日志位置、调试配置等)
app\u name/\uuuuuu init\uuuuuuuuuuuuuuuuuupy
from flask.ext.sqlalchemy import SQLAlchemy
db = SQLAlchemy()
from services.database import db
class Bar(db.Model):
__tablename__ = 'your_MySQL_table_name'
id = db.Column('YourMySQLColumnName', db.Integer, primary_key=True)
name = db.Column('WhateverName', db.String(100))
foo = db.Column(db.ForeignKey('another_MySQLTableName.id'))
class Foo(db.Model):
__tablename__ = 'another_MySQLTableName'
id = db.Column('FooId', db.Integer, primary_key=True)
...
#! /usr/bin/env python
from app_name import create_app
app = create_app(env='local')
if __name__ == '__main__':
app.run()
这是我创建应用程序并初始化db的地方。此db对象将导入并在整个应用程序中使用(即,在模型、测试等中)。我还设置了我的记录器,初始化了我的API和蓝图,并将我的中间件连接到这里(未显示)
app\u name/database.py
from flask.ext.sqlalchemy import SQLAlchemy
db = SQLAlchemy()
from services.database import db
class Bar(db.Model):
__tablename__ = 'your_MySQL_table_name'
id = db.Column('YourMySQLColumnName', db.Integer, primary_key=True)
name = db.Column('WhateverName', db.String(100))
foo = db.Column(db.ForeignKey('another_MySQLTableName.id'))
class Foo(db.Model):
__tablename__ = 'another_MySQLTableName'
id = db.Column('FooId', db.Integer, primary_key=True)
...
#! /usr/bin/env python
from app_name import create_app
app = create_app(env='local')
if __name__ == '__main__':
app.run()
app\u name/models/model\u name.py
from flask.ext.sqlalchemy import SQLAlchemy
db = SQLAlchemy()
from services.database import db
class Bar(db.Model):
__tablename__ = 'your_MySQL_table_name'
id = db.Column('YourMySQLColumnName', db.Integer, primary_key=True)
name = db.Column('WhateverName', db.String(100))
foo = db.Column(db.ForeignKey('another_MySQLTableName.id'))
class Foo(db.Model):
__tablename__ = 'another_MySQLTableName'
id = db.Column('FooId', db.Integer, primary_key=True)
...
#! /usr/bin/env python
from app_name import create_app
app = create_app(env='local')
if __name__ == '__main__':
app.run()
run.py
from flask.ext.sqlalchemy import SQLAlchemy
db = SQLAlchemy()
from services.database import db
class Bar(db.Model):
__tablename__ = 'your_MySQL_table_name'
id = db.Column('YourMySQLColumnName', db.Integer, primary_key=True)
name = db.Column('WhateverName', db.String(100))
foo = db.Column(db.ForeignKey('another_MySQLTableName.id'))
class Foo(db.Model):
__tablename__ = 'another_MySQLTableName'
id = db.Column('FooId', db.Integer, primary_key=True)
...
#! /usr/bin/env python
from app_name import create_app
app = create_app(env='local')
if __name__ == '__main__':
app.run()
我使用run.py
在本地运行应用程序,但我使用nginx+uWSGI在dev/stage/live环境中运行应用程序
我猜除此之外,还有一个
views/
目录。将霍尔格的答案连接到烧瓶上下文的关键是db.Model
是一个声明性的\u base
对象,类似于base
。我花了一段时间才注意到炼金术中这句重要的话
以下是我在应用程序中使用的步骤:
db
对象:db=SQLAlchemy(app)
。注意,在此之前,您需要设置app.config['SQLALCHEMY\u DATABASE\u URI']='connection\u string'db.Model.metadata.reflect(db.engine)
现在,您的
Buildings
类将遵循现有模式。您可以在Python shell中尝试dir(Buildings)
,查看已经列出的所有列 这是另一种设置霍尔格回答中描述的发动机路径的方法。如果用户名或密码中有特殊字符,则很方便
from sqlalchemy.engine.url import URL
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
engine_URL = URL('mssql+pymssql',
username='DOMAIN\\USERNAME',
password="""p@ssword'!""",
host='host.com',
database='database_name')
engine = create_engine(engine_URL)
Base = declarative_base()
Base.metadata.reflect(engine)
我认为通过sqlalchemy使用现有数据库最简单的方法是使用类。文档中的示例代码如下所示:
from sqlalchemy.ext.automap import automap_base
from sqlalchemy.orm import Session
from sqlalchemy import create_engine
Base = automap_base()
# engine, suppose it has two tables 'user' and 'address' set up
engine = create_engine("sqlite:///mydatabase.db")
# reflect the tables
Base.prepare(engine, reflect=True)
# mapped classes are now created with names by default
# matching that of the table name.
User = Base.classes.user
Address = Base.classes.address
session = Session(engine)
# rudimentary relationships are produced
session.add(Address(email_address="foo@bar.com", user=User(name="foo")))
session.commit()
# collection-based relationships are by default named
# "<classname>_collection"
print (u1.address_collection)
从sqlalchemy.ext.automap导入automap\u base
从sqlalchemy.orm导入会话
来自sqlalch