在 Django 用户模型中处理权限缓存

Handle permission cache in django user model

我偶然发现了一个奇怪的行为:我向用户对象添加了权限,但权限检查失败。

permission = Permission.objects.get_by_natural_key(app_label='myapp', codename='my_codename', model='mymodel')
user.user_permissions.add(permission)

user.has_permission('myapp.my_codename') # this is False!

我找到了一些关于用户权限缓存的帖子here and here,解决方案似乎是从数据库中完全重新加载对象。

# Request new instance of User
user = get_object_or_404(pk=user_id)

# Now note how the permissions have been updated
user.has_perms('myapp.my_codename') # now it's True

这对我来说似乎真的太过分了,而且非常不像 django。真的没有办法像使用 refresh_from_db()?

那样清除权限缓存或重新加载外键吗?

提前致谢!
罗尼

由于 has_perms 方法,缓存对您来说只是一个问题。如果你一直跟着它向下堆栈,你最终会得到 here。您会看到此方法在继续之前明确检查缓存。

如果你真的此时需要知道这个用户的权限并且真的不想从数据库刷新, 然后你可以在没有 has_perm 辅助方法的情况下检查更多 manually/directly,因为这个权限 .add() 是一个标准的 m2m 操作并且模型字段已经更新。

在实践中,您不太可能在添加权限后立即检查权限,此时对象在范围内并且权限已缓存,因为它有点多余。我确定 Django 开发人员考虑了这一点,并认为默认为您缓存它的好处是正确的选择。

您可以通过删除用户对象的 _perm_cache_user_perm_cache 来强制重新计算。

permission = Permission.objects.get_by_natural_key(app_label='myapp', codename='my_codename', model='mymodel')
user.user_permissions.add(permission)
user.has_permission('myapp.my_codename') # returns False

del user._perm_cache
del user._user_perm_cache
user.has_permission('myapp.my_codename') # should be True

但这实际上会再次访问数据库以获取更新的权限。由于这些是基于 django 的内部工作而不是 public API 的一部分,这些缓存键将来可能会改变,所以我仍然建议再次获取用户。但这完全取决于你。