我的应用程序具有可重现的错误published on github
错误的简短描述:SQLAlchemy使用子查询,但忽略ORDER_BY表达式中的子查询别名。
型号:
from flask.ext.sqlalchemy import SQLAlchemy
db = SQLAlchemy()
class User(db.Model):
__tablename__ = 'users'
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String)
class Genre(db.Model):
__tablename__ = 'genres'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String, nullable=False)
class Magazine(db.Model):
__tablename__ = 'magazines'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String, nullable=False)
author_id = db.Column(db.Integer, db.ForeignKey('users.id'))
genre_id = db.Column(db.Integer, db.ForeignKey('genres.id'))
author = db.relationship(User,
backref=db.backref('magazines',
order_by=id,
lazy='joined'))
genre = db.relationship(Genre,
backref=db.backref('magazines',
order_by=id,
lazy='joined'))
class WorkType(db.Model):
__tablename__ = 'work_types'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String, nullable=False)
class WorkEvent(db.Model):
__tablename__ = 'work_events'
id = db.Column(db.Integer, primary_key=True)
start_date = db.Column(db.DateTime, nullable=False)
end_date = db.Column(db.DateTime, nullable=False)
work_type_id = db.Column(db.Integer, db.ForeignKey('work_types.id'))
work_type = db.relationship(WorkType,
backref=db.backref('work_events'), order_by=id,
lazy='joined')
class AuthorRate(db.Model):
__tablename__ = 'author_rates'
id = db.Column(db.Integer, primary_key=True)
amount = db.Column(db.Float, nullable=False)
work_type_id = db.Column(db.Integer, db.ForeignKey('work_types.id'))
author_id = db.Column(db.Integer, db.ForeignKey('users.id'))
work_type = db.relationship(WorkType,
backref=db.backref('author_rates'), order_by=id,
lazy='joined')
author = db.relationship(User,
backref=db.backref('author_rates'),
order_by=id, lazy='joined')
的观点:
@app.route('/')
def index():
for i in range(5):
some_key = str(random.randint(1000000, 9000000))
work_type = WorkType(name='work_type' + some_key)
db.session.add(work_type)
for j in range(8):
some_other_key = str(random.randint(1000000, 9000000))
user = User(username='user' + some_key + some_other_key)
db.session.add(user)
rate = AuthorRate(
amount=1 + random.random(),
work_type=work_type,
author=user)
db.session.add(rate)
db.session.commit()
print('========')
rates = AuthorRate.query
print(rates)
rates = rates.limit(10)
print('+++++++')
print(rates)
print('=========')
rates = rates.offset(0)
return render_template('limit.html', rates=rates)
模板:
{% for rate in rates %}
<p>{{ rate.id }} - {{ rate.amount }} - {{ rate.work_type }} - {{ rate.author }}</p>
{% endfor %}
这是调用.limit()之前和之后的SQL表达式。
-- Initial
SELECT
author_rates.id AS author_rates_id, author_rates.amount AS author_rates_amount, author_rates.work_type_id AS author_rates_work_type_id, author_rates.author_id AS author_rates_author_id, work_types_1.id AS work_types_1_id, work_types_1.name AS work_types_1_name, users_1.id AS users_1_id, users_1.username AS users_1_username, magazines_1.id AS magazines_1_id, magazines_1.name AS magazines_1_name, magazines_1.author_id AS magazines_1_author_id, magazines_1.genre_id AS magazines_1_genre_id
FROM author_rates
LEFT OUTER JOIN work_types AS work_types_1 ON work_types_1.id = author_rates.work_type_id
LEFT OUTER JOIN users AS users_1 ON users_1.id = author_rates.author_id
LEFT OUTER JOIN magazines AS magazines_1 ON users_1.id = magazines_1.author_id ORDER BY author_rates.id, author_rates.id, magazines_1.id
-- Final
SELECT
anon_1.author_rates_id AS anon_1_author_rates_id, anon_1.author_rates_amount AS anon_1_author_rates_amount, anon_1.author_rates_work_type_id AS anon_1_author_rates_work_type_id, anon_1.author_rates_author_id AS anon_1_author_rates_author_id, work_types_1.id AS work_types_1_id, work_types_1.name AS work_types_1_name, users_1.id AS users_1_id, users_1.username AS users_1_username, magazines_1.id AS magazines_1_id, magazines_1.name AS magazines_1_name, magazines_1.author_id AS magazines_1_author_id, magazines_1.genre_id AS magazines_1_genre_id
FROM (
SELECT author_rates.id AS author_rates_id, author_rates.amount AS author_rates_amount, author_rates.work_type_id AS author_rates_work_type_id, author_rates.author_id AS author_rates_author_id
FROM author_rates
LIMIT 10 OFFSET 0) AS anon_1
LEFT OUTER JOIN work_types AS work_types_1 ON work_types_1.id = anon_1.author_rates_work_type_id
LEFT OUTER JOIN users AS users_1 ON users_1.id = anon_1.author_rates_author_id
LEFT OUTER JOIN magazines AS magazines_1 ON users_1.id = magazines_1.author_id
ORDER BY author_rates.id, author_rates.id, magazines_1.id;
错误: ProgrammingError:(psycopg2.ProgrammingError)缺少表&#34; author_rates&#34;的FROM子句条目 第4行:... _ 1 ON users_1.id = magazines_1.author_id ORDER BY author_rat ...
热订单应该是:
ORDER BY anon_1.author_rates_id, magazines_1.id;
问题:有解决方法吗?
环境: ubuntu 14.04,python 2.7,SQLAlchemy 1.0.8,Flask-SQLAlchemy 2.0,Flask 0.10.1 Stack trace
P.S。模型可能看起来有点奇怪,因为问题的根源在闭源应用程序中,我没有足够的想象力来编写好的概念证明