用于从DAL选择中排除某些值的查询或表达式

时间:2012-04-12 03:51:09

标签: google-app-engine data-access-layer web2py

我正在尝试从我的选择中排除包含名为meta的标记的帖子:

meta_id = db(db.tags.name == "meta").select().first().id
not_meta = ~db.posts.tags.contains(meta_id)
posts=db(db.posts).select(not_meta)

但这些帖子仍然出现在我的选择中。

写这个表达的正确方法是什么?

我的表格如下:

db.define_table('tags',
    db.Field('name', 'string'),
    db.Field('desc', 'text', default="")
)

db.define_table('posts', 
    db.Field('title', 'string'),
    db.Field('message', 'text'),
    db.Field('tags', 'list:reference tags'),
    db.Field('time', 'datetime', default=datetime.utcnow())
)

我在GAE上使用W​​eb2Py 1.99.7,在Python 2.7.2上使用High Replication DataStore

更新

我刚刚按照@Anthony的建议尝试了posts=db(not_meta).select(),但它给了我一张带有以下追溯的票证:

Traceback (most recent call last):
  File "E:\Programming\Python\web2py\gluon\restricted.py", line 205, in restricted
    exec ccode in environment
  File "E:/Programming/Python/web2py/applications/vote_up/controllers/default.py", line 391, in <module>
  File "E:\Programming\Python\web2py\gluon\globals.py", line 173, in <lambda>
    self._caller = lambda f: f()
  File "E:/Programming/Python/web2py/applications/vote_up/controllers/default.py", line 8, in index
    posts=db(not_meta).select()#orderby=settings.sel.posts, limitby=(0, settings.delta)
  File "E:\Programming\Python\web2py\gluon\dal.py", line 7578, in select
    return adapter.select(self.query,fields,attributes)
  File "E:\Programming\Python\web2py\gluon\dal.py", line 3752, in select
    (items, tablename, fields) = self.select_raw(query,fields,attributes)
  File "E:\Programming\Python\web2py\gluon\dal.py", line 3709, in select_raw
    filters = self.expand(query)
  File "E:\Programming\Python\web2py\gluon\dal.py", line 3589, in expand
    return expression.op(expression.first)
  File "E:\Programming\Python\web2py\gluon\dal.py", line 3678, in NOT
    raise SyntaxError, "Not suported %s" % first.op.__name__
SyntaxError: Not suported CONTAINS

更新2:

由于~目前没有使用数据存储的GAE,我使用以下作为临时解决方法:

meta = db.posts.tags.contains(settings.meta_id)
all=db(db.posts).select()#, limitby=(0, settings.delta)
meta=db(meta).select()
posts = []
i = 0
for post in all:
    if i==settings.delta: break
    if post in meta: continue
    else:
        posts.append(post)
        i += 1
#settings.delta is an long integer to be used with limitby

1 个答案:

答案 0 :(得分:1)

尝试:

meta_id = db(db.tags.name == "meta").select().first().id
not_meta = ~db.posts.tags.contains(meta_id)
posts = db(not_meta).select()

首先,您的初始查询返回一个完整的Row对象,因此您只需要提取“id”字段。其次,not_meta是一个Query对象,因此它进入db(not_meta)以创建一个Set对象,定义要选择的记录集(select()方法为每个记录返回一个字段列表记录,以及一些其他参数,例如orderbygroupby等。)