python - 以 UUID 字段作为主键的 Django 管理员 UserChangeForm
问题描述
我正在开发一个包含敏感用户数据的 Django 应用程序,因此我正在采取一些步骤来匿名用户对象及其数据。
我创建了子类 AbstractBaseUser 模型的自定义“用户”对象,如下所示:
class User(AbstractBaseUser, PermissionsMixin):
(...)
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
(...)
它具有以下链接ModelAdmin
对象:
from django.contrib.auth.forms import UserChangeForm
@admin.register(User)
class UserAdmin(admin.ModelAdmin):
form = UserChangeForm
我使用 UUID 字段作为主键以确保最大程度的匿名性,但我希望能够在 Django Admin 中重置用户密码(就像你可以使用默认User
对象一样)
但是,当我在管理员中打开用户并按链接更改密码时,我收到以下错误消息:
User with ID "21362aca-6918-47ea-9b29-275350a89c54/password" doesn't exist. Perhaps it was deleted?
管理员 url 仍然需要一个以整数作为其pk
值的 url。
所以看来我必须覆盖 ModelAdmin 定义中的管理 url 配置,但我想知道是否有更简单的方法来实现所需的结果 - 因为我想用 UUID 字段替换 User.pk 是相当常规的发生,我想象许多开发人员都遇到了这个问题。我试图找到某种设置/切换来实现这一点,但无济于事,我错过了什么吗?
解决方案
您的 'UserAdmin' 继承自ModelAdmin
,它通过get_urls
添加、更改、删除等视图的方法提供 url,但也提供 'fallback' url:
urlpatterns = [
#...
url(r'^(.+)/change/$', wrap(self.change_view), name='%s_%s_change' % info),
# For backwards compatibility (was the change url before 1.9)
path('<path:object_id>/', wrap(RedirectView.as_view(
pattern_name='%s:%s_%s_change' % ((self.admin_site.name,) + info)
))),
]
您关注的 url 看起来/user/<UUID>/password/
只适合后备模式的正则表达式 - 它会将您重定向到更改页面,使其<UUID>/password
用作object_id
.
尝试从继承,django.contrib.auth.admin.UserAdmin
因为它的get_urls
方法提供了您需要的 url 模式。
更多的探索...
如果您的主键字段是 AutoField,则整个过程会ValueError('invalid literal for int')
在尝试强制转换int('some_integer/password')
以django.db.models.fields.AutoField.get_prep_value
准备查询值时引发 a。可以理解!
HOWEVER:UUIDField
使用get_prep_value
基类的方法Field
。Field.get_prep_value
只是简单地返回值,甚至不检查(毕竟,验证值应该是工作UUIDField
)。因此,您最终会得到一个查找虚假 uuid 的查询'<uuid>/password'
,这显然不存在。
推荐阅读
- rust - 如何解决基本借款问题?
- python - 最快(最少执行时间)的方法来获取 int 数组的最大值/最小值,除了 range() 和 len() 之外没有内置函数
- python - 在python中执行定义为DAG的任务的简单方法?
- rust - 获取当前时间戳
- mysql - 更新新旧版本之前的 MySQL 触发器
- powerbi - 根据过滤器更改表的列
- spring-boot - 将 ssl 添加到域后,Swagger Doc 无法正常工作
- c - While循环等待中断处理程序
- jsf - jakarta 9.1 Facelets XHTML 页面命名空间指令
- powerbi - 钻取矩阵的一列