web2py 为组成员验证数据库模型

web2py validating db model for group menbers

我正在使用 web2py,并正在尝试为 auth_user 构建一个字段,该字段应该被验证为某个组的成员。因此,在 models/db.py 中,我添加了一个字段,告诉用户谁是管理员:

auth.settings.extra_fields['auth_user']=[Field('manager', 'reference auth_user')]

然后我设置了 db.auth_userdb.auth_groupdb.auth_membership 来包含属于组 'managers'

的用户

我现在想要实现的是验证用户输入,以便 auth_user 的 'manager' 字段只能包含组 'managers' 中的用户。我已经经历了很多变化,以下可能在我看来最接近理论上的意义:

group_id = auth.id_group('managers') 
all_users_in_group = db(db.auth_membership.group_id==group_id)._select(db.auth_membership.user_id)
db.auth_user.auditor.requires = IS_IN_DB(db, db(~db.auth_user.id.belongs(all_users_in_group)).select(db.auth_user.id)) 

但即使这样也失败了

<type 'exceptions.AttributeError'>('Table' object has no attribute 'managers')

我的问题的完美解决方案将显示在下拉菜单中,而不是 auth_user.id,而是 auth_user.first_nameauth_user.last_name 连接。

我确实设法解决了这个问题,但我绝对不会称之为优雅。在 web2py 中会有更惯用的方法来做到这一点吗?以下是我添加到 models/db.py

中的内容
group_id = auth.id_group('managers')
rows=db(db.auth_membership.group_id==group_id).select(db.auth_membership.user_id)
rset=set()
for r in rows:
    rset.add(int((r.user_id)))

db.auth_user.auditor.requires = IS_IN_DB(db(db.auth_user.id.belongs(rset)), db.auth_user.id, '%(first_name)s %(last_name)s')

您在 中已经正确完成了它,但您可以改进它。

验证器的第一个参数可以是数据库连接或DAL Set。所以你可以通过 直接将数据库查询作为第一个参数,像这样

query = db((db.auth_membership.group_id == auth.id_group('managers')) &
           (db.auth_membership.user_id == db.auth_user.id))
db.auth_user.auditor.requires = IS_IN_DB(query, db.auth_user.id, '%(first_name)s %(last_name)s')

您也可以像下面这样写查询:

query = db((db.auth_group.role == 'managers') &
           (db.auth_membership.group_id == db.auth_group.id) &
           (db.auth_membership.user_id == db.auth_user.id))

我使用了与以下类似的代码并确认它适用于 web2py 2.17.2-stable+timestamp.2018.10.06.18.54.02(运行 on nginx/1.14.0,Python 3.6.7). 之前的回答不适用于这个版本.

group_id = auth.id_group('managers')
user_rows = db(db.auth_membership.group_id == group_id)._select(db.auth_membership.user_id)
query = db(db.auth_user.id.belongs(user_rows))
db.auth_user.auditor.requires = IS_IN_DB(query, db.auth_user.id, '%(first_name)s %(last_name)s'