Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/347.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 我是否可以检查sqlalchemy查询对象以查找已连接的表?_Python_Join_Sqlalchemy_Flask Sqlalchemy - Fatal编程技术网

Python 我是否可以检查sqlalchemy查询对象以查找已连接的表?

Python 我是否可以检查sqlalchemy查询对象以查找已连接的表?,python,join,sqlalchemy,flask-sqlalchemy,Python,Join,Sqlalchemy,Flask Sqlalchemy,我试图以编程方式构建一个搜索查询,为此,我加入了一个表 class User(db.Model): id = db.Column(db.Integer(), primary_key=True) class Tag(db.Model): id = db.Column(db.Integer(), primary_key=True) user_id = db.Column(db.Integer(), db.ForeignKey('user.id')) title =

我试图以编程方式构建一个搜索查询,为此,我加入了一个表

class User(db.Model):
    id = db.Column(db.Integer(), primary_key=True)

class Tag(db.Model):
    id = db.Column(db.Integer(), primary_key=True)
    user_id = db.Column(db.Integer(), db.ForeignKey('user.id'))
    title = db.Column(db.String(128))
    description = db.Column(db.String(128))
这是一个有点做作的例子——我希望它有意义

假设我的搜索功能类似于:

def search(title_arg, desc_arg):
    query = User.query
    if title_arg:
        query = query.join(Tag)
        query = query.filter(Tag.title.contains(title_arg))
    if desc_arg:
        query = query.join(Tag)
        query = query.filter(Tag.description.contains(desc_arg))

    return query
以前,我一直跟踪哪些表已经加入到列表中,如果该表在列表中,假设它已经加入,只需添加过滤器

如果我可以查看查询对象,看到
标记
已经被加入,并跳过它,那就太酷了。我有一些更复杂的查询构建,这将真正受益于此


如果我错过了一个完全不同的搜索查询构建策略,那也太好了。或者,如果上面的代码是好的,如果我加入表两次,这也是很好的信息。非常感谢您的帮助

您可以在
查询中找到已联接的表。\u join\u entities

joined_tables = [mapper.class_ for mapper in query._join_entities]

根据r-m-n的回答:

在项目初始化过程中,向
sqlalchemy.orm.Query
对象添加
unique\u join
方法,如下所示:

def unique_join(self, *props, **kwargs):
    if props[0] in [c.entity for c in self._join_entities]:
        return self
    return self.join(*props, **kwargs)

Query.unique_join = unique_join
现在使用
query.unique\u join
代替
query.join

query = query.unique_join(Tag)

自SQLAlchemy 1.4以来,早期提出的解决方案(包括
\u join\u实体
)不再有效

SQLAlchemy 1.4 我试图在SQLAlchemy 1.4中解决这个问题,但有一个警告:

  • 这种方法包括查询中的所有实体,因此不仅仅是连接的实体
来自sqlalchemy.sql导入访问者
从上下文库导入抑制
def_具有_实体(自身、模型)->bool:
在visitors.iterate(self.statement)中针对visitor:
#检查“.join(Parent.child)`子句
如果访问者访问名称为二进制:
对于访客中的vis。迭代(访客):
#访问者可能没有表属性
使用抑制(AttributeError):
#根据表名验证是否已存在
如果model.\uuuu table\uuuu.fullname==vis.table.fullname:
返回真值
#检查“.join(Child)`子句
如果是访客,请访问\u名称\uuuu=='表格':
#来访者可能是个收藏家左右,
#这是无法与模型相比的
使用抑制(TypeError):
如果model==visitor.entity\u名称空间:
返回真值
返回错误
def唯一_连接(自身、型号、*args、**kwargs):
“”“如果给定模型尚未在查询中,则加入”“”
如果不是self.\u有\u实体(模型):
self=self.join(型号,*args,**kwargs)
回归自我
查询.\u has\u entity=\u has\u entity
Query.unique\u join=unique\u join

SQLAlchemy“查找已连接的表”是您需要跳过重复连接的内容。问你的问题总是一个好的做法,而不是用你头脑中的方式来解决它。例如,询问“如果一个表已经加入,如何跳过加入”。根据@mtoloo,加入的表也可以是
[mapper.entity For mapper in query.\u join\u entities]
。这一直到SQLAlchemy 1.3,但是
\u join\u entities
似乎不再存在于1.4中。@jelleklaver您是否为“\u join\u entities”找到了任何解决方法?@Omnia69,还没有完全解决。但是我已经找到了一个部分解决方案,使用
sqlalchemy.sql中的
visitors
v.entity\u visitors中的v名称空间。如果v.\uu visit\u name\uuu==“table”
,则迭代(query.statement)。只有在join语句中直接使用该类时,这才有效。因此它不适用于
.join(Parent.child)
,但适用于
.join(child)
。它还包括select语句中添加的实体,这可能是您不想要的。