常用过滤器,如何访问相关记录?

Common filters, how to access related record?

我想检查 places 中的记录 auth_user 是否在分配给站点的组中,而不是 children:

Sites = db.define_table("sites",
                        ..
                        Field("visible_for", db.auth_group,default=1,writable=True),
                       )

Places = db.define_table("places",
                        ..
                         Field("sited_in", db.sites),
                         Field("created_by", db.auth_user,default=auth.user_id,update=auth.user_id,writable=True),
                   
                         common_filter = lambda query: (db.places.created_by == auth.user.id or auth.has_membership(db.places.sited_in.visible_for)
                        )

我做错了什么,因为第一部分有效但第二部分不适用?

common_filter函数必须return一个DAL查询,以下不是查询:

db.places.created_by == auth.user.id or auth.has_membership(db.places.sited_in.visible_for)

它不是查询,因为 (a) 它使用 Python 关键字 or,而 DAL 查询必须改用 | 运算符,并且 (b) auth.has_membership 不是 return 查询而是 return 一个布尔值。此外,db.places.sited_in.visible_for 无效(一旦您 select 从 db.places 编辑了特定记录,您可以通过 row.sited_in.visible_for 获取关联站点的 visible_for 字段,但 db.places.sited_in 只是一个 DAL Field 对象,没有 visible_for 属性)。

如果要检查组成员身份,则必须构造适当的查询。一种方法是使用带有嵌套 select 的 belongs 查询,如 here:

所述
authorized_sites = db(
    db.sites.visible_for.belongs(auth.user_groups.keys()))._select(db.sites.id)

Places = db.define_table('places',
    ...,
    common_filter = lambda query: (db.places.created_by == auth.user.id) |
        db.places.sited_for.belongs(authorized_sites))

我相信您也可以对嵌套 select 使用以下快捷方式,只需将 db.sites 查询直接传递给 belongs 方法即可:

Places = db.define_table('places',
    ...,
    common_filter = lambda query: (db.places.created_by == auth.user.id) |
        db.places.sited_for.belongs(
            db.sites.visible_for.belongs(auth.user_groups.keys())))

auth.user_groups 是用户所属的所有 auth_groups 的字典,组 id 作为键,role 作为键作为值(因此 auth.user_groups.keys() 是用户组 id 的列表)。请注意,auth.user_groups 仅在登录时确定一次,然后存储在会话中,因此如果用户的组成员身份在登录后发生更改,则可能不会 up-to-date。确保最多 up-to-date 数据,您将不得不查询以获取用户当前的一组组成员资格。