我有一个Django系统,它使用Guardian的User Object Manager进行访问控制。我想写一个函数,查找与“旧”用户关联的所有内容类型的所有权限,并将其分配给“新”用户。我不能直接查询UserObjectPermission
,因为我们的系统出于性能原因使用直接外键模型。
这是一个 * 我想要的 * 的例子
from django.contrib.auth.models import User
from guardian.shortcuts import get_objects_for_user, assign_perm
def update_permissions_for_user(old_user, new_user):
# Retrieve all USER permission objects for the old user
# this throws exception because it requires a perms param that I do not want to provide. I want all objects across all models
old_user_permissions = get_objects_for_user(old_user, use_groups=False, any_perm=False, with_superuser=False, accept_global_perms=False)
# Iterate through each permission object and update it to point to the new user
for permission in old_user_permissions:
assign_perm(permission.codename, new_user, permission)
remove_perm(permission.codename, old_user, permission)
# Example usage:
old_user = User.objects.get(username='old_username') # Replace 'old_username' with the actual username
new_user = User.objects.get(username='new_username') # Replace 'new_username' with the actual username
update_permissions_for_user(old_user, new_user)
字符串
如果我们不使用直接外键模型,代码将简单地是:
user_objects_permission_qs = UserObjectPermission.objects.filter(user=current_user)
affected_rows = user_objects_permission_qs.update(user=new_user)
型
然而,* 我想要的 * 示例的问题是,get_objects_for_user
需要perms
参数。
如果序列中存在多个权限,则它们的内容类型必须相同,否则将引发MixedContentTypeError异常。
所以这不能用于不同内容类型的对象。有什么建议吗?我也考虑过使用get_user_perms,但这也需要一个对象参数。
下面是我们如何创建直接外键模型
class MyModelUserObjectPermission(UserObjectPermissionBase):
content_object = models.ForeignKey(MyModel, on_delete=models.CASCADE)
型
发布脚本
@willeM_货车Onsem解决方案在SQLite中运行良好,但在MySQL中引发以下错误。
此外,我们必须显式地检查UserObjectPermission类(因为对于某些模型,我们仍然使用它),并由于它具有不同的模式而以不同的方式对待这个模型
You can't specify target table 'tablename' for update in FROM clause"
型
我们必须将~Exists
更改为.exclude()
。在MySQL中,您不能在同一语句中连接要更新的表
1条答案
按热度按时间p3rjfoxz1#
在这种情况下,我们可能会在“bulk”中这样做,例如,
UserObjectPermissionBase
的每个子类都有一个查询。然而,有一个可能的警告:如果我们想将权限分配给新用户,并且用户已经获得了该权限。单个模型的查询如下所示:
字符串
但如果新用户的许可已经存在,则这将失败,因为存在将失败的唯一性约束。
但是我们可以 look before we leap [wiki],使用:
型
因此,这将首先检查我们是否可以更改它,以便对于相同的对象,权限和新用户没有
MyModelUserObjectPermission
。如果是这样,我们将更新它。在第二个查询中,我们将删除旧用户仍然存在的权限。现在我们唯一需要做的就是为 all 模型做这件事,我们可以通过查找
UserObjectPermissionBase
的子类来做到这一点:型
在这里,我们首先将类的层次结构隔离开来,寻找
UserObjectPermissionBase
的所有子类,接下来我们将为所有这些非抽象的模型调用change_perm_for_klass(…)
。当然,只有当您通过定义
UserObjectPermissionBase
的子类来实现django-guardian
时,逻辑才有效。