Sco*_*oks -1 python sqlalchemy flask flask-sqlalchemy
在我问之前,我会承认这是一个奇怪的问题。我想知道是否可以使用原始 SQL 而不是使用方法本身来复制 Flask/SQL Alchemy 类方法?
长话短说,我和我的队友正在参加数据库设计课程,我们现在处于实施阶段,我们正在编写基于我们的数据库架构设计的应用程序。我们想让事情变得简单,所以我们选择在 Python 中使用 Flask。我们正在关注Flask Mega 教程,这是一个解释如何像我们所做的那样构建基本站点的精彩教程。我们刚刚完成了第 5 章:用户登录,并且正在继续。
在app/routes.py脚本中,教程做了一些事情来获取用户信息。以下是示例应用程序的示例登录路径:
from flask_login import current_user, login_user
from app.models import User
# ...
@app.route('/login', methods=['GET', 'POST'])
def login():
if current_user.is_authenticated:
return redirect(url_for('index'))
form = LoginForm()
if form.validate_on_submit():
user = User.query.filter_by(username=form.username.data).first()
if user is None or not user.check_password(form.password.data):
flash('Invalid username or password')
return redirect(url_for('login'))
login_user(user, remember=form.remember_me.data)
return redirect(url_for('index'))
return render_template('login.html', title='Sign In', form=form)
Run Code Online (Sandbox Code Playgroud)
该行user = User.query.filter_by(username=form.username.data).first()是我感兴趣的。基本上,该行实例化了User类,它是来自 SQL Alchemy 的数据库模型,并从用户输入的电子邮件地址中获取有关用户的信息。调用这些方法会生成一条 SQL 语句,如下所示:
SELECT `User`.`userID` AS `User_userID`,
`User`.user_email AS `User_user_email`,
`User`.user_first_name AS `User_user_first_name`,
`User`.user_last_name AS `User_user_last_name`,
`User`.user_password AS `User_user_password`
FROM `User`
WHERE `User`.user_email = 'test@test.com'
LIMIT 1
Run Code Online (Sandbox Code Playgroud)
还有一些关于user变量本身的信息:
>>> print(type(user))
<class 'myapp.models.User'>
>>> pp(user.__dict__)
{'_sa_instance_state': <sqlalchemy.orm.state.InstanceState object at 0x7f5a026a8438>,
'userID': 1,
'user_email': 'test@test.com',
'user_first_name': 'SomeFirstName',
'user_last_name': 'SomeLastName',
'user_password': 'somepassword'}
Run Code Online (Sandbox Code Playgroud)
在我们的项目中,我们不应该使用像调用query.filter_by(username=form.username.data).first()实例化User类那样生成的 SQL 语句;我们应该自己编写原始 SQL,这通常没有意义,但在我们的例子中确实如此。
这可能吗?
首先:与您的教授或助教交谈。不要对如此重大的事情做假设,这样可以节省自己的时间。如果该课程的目标是考虑数据库模式设计,那么使用 ORM 可能没问题。如果您需要编写自己的 SQL,则不要使用 ORM 开头。
回答技术问题:是的,您可以将 SQLAlchemy 纯粹用作数据库连接池,用作从 Python 对象创建有效 SQL 语句的工具,以及成熟的 ORM,以及介于两者之间的每个级别。
例如,使用 ORM 层,您可以告诉Query对象不要为您生成 SQL,而是获取文本。这在使用文本 SQL部分下的 SQLAlchemy ORM 教程中有介绍:
文字字符串可以灵活地与 Query 一起使用,通过指定它们与
text()构造的使用,这是大多数适用方法接受的
对于您的登录示例,仅查询密码可能如下所示:
user = User.query.from_statement(
db.text("SELECT * FROM User where user_email=:email LIMIT 1")
).params(email=form.username.data).first()
if user is None or user.check_password(form.password.data):
# ...
Run Code Online (Sandbox Code Playgroud)
您还可以阅读SQL Expression API(SQLAlchemy 库的核心API)以使用 Python 代码构建查询;Python 对象和结果查询之间的关系几乎是一对一的;您通常会首先生成表的模型,然后从那里构建 SQL,或者您可以使用文字:
s = select([
literal_column("User.password", String)
]).where(
literal_column("User.user_email") == form.username.data
).select_from(table("User")).limit(1)
Run Code Online (Sandbox Code Playgroud)
并使用该方法执行此类对象Session.execute()
results = db.session.execute(s)
Run Code Online (Sandbox Code Playgroud)
如果你真的想用脚射自己,你也可以db.session.execute()直接将字符串传递给:
results = db.session.execute("""
SELECT user_password FROM User where user_email=:email LIMIT 1
""", {'email': form.username.data})
Run Code Online (Sandbox Code Playgroud)
只知道Session.execute()返回一个ResultProxy()实例,而不是 ORM 实例。
另外,要知道 Flask-Login不需要您使用 ORM。正如项目文档所述:
但是,它不会:
- 对您强加特定的数据库或其他存储方法。您完全负责如何加载用户。
因此,您可以手动创建每次查询数据库时实例化的子类UserMixin。
class User(flask_login.UserMixin):
def __init__(self, id): # add more attributes as needed
self.id = id
@login_manager.user_loader
def load_user(user_id):
# perhaps query the database to confirm the user id exists and
# load more info, but all you basically need is:
return User(user_id)
# on login, use
user = User(id_of_user_just_logged_in)
login_user(user)
Run Code Online (Sandbox Code Playgroud)
就是这样。扩展希望看到情况下实现4种基本方法和UserMixin类提供所有这些,你只需要提供的id属性。如何验证用户 ID 和处理登录取决于您。
| 归档时间: |
|
| 查看次数: |
3929 次 |
| 最近记录: |