0

我使用flask-sqlalchemy 发表了这个声明,并且我选择将其保留为原始形式。Post.query相当于session.query(Post)

我尝试创建一个子查询,该子查询将过滤掉数据库中处于草稿状态且不是由当前用户创建或修改的所有帖子。我做了这个查询,

Post.query\
    .filter(sqlalchemy.and_(
        Post.post_status != Consts.PostStatuses["Draft"],
            sqlalchemy.or_(
                Post.modified_by_id == current_user.get_id(),
                Post.created_by_id == current_user.get_id()))

这创造了:

Where true AND ("Post".modified_by_id = :modified_by_id_1 OR  
"Post".created_by_id = :created_by_id_1)

预期结果:

Where "Post".post_status != "Draft" AND (
"Post".modified_by_id = :modified_by_id_1 OR  
"Post".created_by_id = :created_by_id_1)

我想知道,为什么会这样?如何提高 SQLAlchemy 中的错误级别?我认为我的项目正在悄然失败,我想证实我的猜测。

更新:

我使用了错误的常量字典。一个字典包含整数,另一个包含字符串(一个用于数据库查询,一个用于打印)。

_post_status = db.Column(
        db.SmallInteger,
        default=Consts.post_status["Draft"]) 

post_status 包含整数, Consts.PostStatuses 包含字符串。事后看来,真是个坏主意。我将制作一个返回元组而不是两个字典的字典。

@property
def post_status(self):
    return Consts.post_status.get(getattr(self, "_post_status", None))
4

1 回答 1

2

问题是您的post_status属性不能在 ORM 级别查询中使用,因为这是一个python 描述符,默认情况下在类级别返回自身:

from sqlalchemy import *
from sqlalchemy.orm import *
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()

class A(Base):
    __tablename__ = 'a'

    id = Column(Integer, primary_key=True)

    _post_status = Column(String)

    @property
    def post_status(self):
        return self._post_status


print (A.post_status)
print (A.post_status != 5678)

输出:

$ python test.py
<property object at 0x10165bd08>
True

您正在寻找的使用类型看起来像一个混合属性,它是一个包含 SQLAlchemy 的对“常规”python 描述符的扩展,它产生与核心 SQL 表达式兼容的类级行为:

from sqlalchemy.ext.hybrid import hybrid_property

class A(Base):
    __tablename__ = 'a'

    id = Column(Integer, primary_key=True)

    _post_status = Column(String)

    @hybrid_property
    def post_status(self):
        return self._post_status

print (A.post_status)
print (A.post_status != 5678)

输出:

$ python test.py
A._post_status
a._post_status != :_post_status_1

一定要仔细阅读混合文档,包括如何建立正确的 SQL 表达式行为,在实例和类级别都工作的描述符是一种有点高级的 Python 技术。

于 2013-10-14T17:47:49.637 回答