<p>我想我找到了一个暂时可以接受的答案,但是它使用了SQLAlchemy的内部信息(一个带下划线前缀的字段)。在</p>
<p>问题的核心是,由于我处理的是来自用户的解析信息,所以我从一个类的名称和要导航的关系的名称开始。例如在<code>plant where accession.species.id=44</code>中,类名是<code>Plant</code>,我正在对连接的<code>Species</code>对象的<code>id</code>进行过滤。在</p>
<p>上面的例子可能会让人觉得事情很简单,只是一个资本化问题。但是我们仍然需要知道<code>Plant</code>,<code>Accession</code>,和{<cd4>}在哪个模块中被找到。在</p>
<p>另一个例子:<code>family where genera.id!=0</code>。一般来说,关系的名称不必等于所引用的类的名称。在</p>
<p>语法没问题,我不需要再改了。问题是(而且部分仍然是)在与SQLAlchemy的交互中,所以我不得不更正<code>IdentifierToken</code>和{<cd11>}类中的<code>evaluate</code>方法。在</p>
<p>我的解决方案包括以下代码:</p>
<pre><code>class IdentifierToken(object):
....
def evaluate(self, env):
"""return pair (query, attribute)
the value associated to the identifier is an altered query where the
joinpoint is the one relative to the attribute, and the attribute
itself.
"""
query = env.session.query(env.domain)
if len(self.value) == 1:
# identifier is an attribute of the table being queried
attr = getattr(env.domain, self.value[0])
elif len(self.value) > 1:
# identifier is an attribute of a joined table
query = query.join(*self.value[:-1], aliased=True)
attr = getattr(query._joinpoint['_joinpoint_entity'], self.value[-1])
return query, attr
class IdentExpressionToken(object):
...
def evaluate(self, env):
q, a = self.operands[0].evaluate(env)
clause = lambda x: self.operation(a, x)
return q.filter(clause(self.operands[1].express()))
</code></pre>
<p>一些要点:</p>
<ul>
<li>最初我不清楚query方法没有改变调用它的查询,但是我必须使用返回值。在</li>
<li>我对连接的查询取别名,以便很容易检索联接操作的“destination”类。在</li>
<li>对于别名联接查询,我使用的是字段<code>_joinpoint</code>,它看起来像是未公开的信息。在</li>
<li><p><code>query._joinpoint['_joinpoint_entity']</code>是对类的引用,我需要从中检索解析查询中命名的字段。<code>_joinpoint</code>字典在非别名查询上看起来不同。</p></li>
<li><p>这个问题仍然悬而未决的部分是,是否有一种“官方的”SQLAlchemy方法来检索这些信息。</p></li>
</ul>