具有UUID字段作为主键的Django管理员UserChangeForm

时间:2018-11-05 16:06:28

标签: python django django-admin

我正在开发一个包含敏感用户数据的Django应用,因此我采取了许多步骤来匿名化User对象及其数据。

我创建了自定义“用户”对象,该对象将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定义中覆盖admin url配置,但我想知道是否有一种更简单的方法来实现所需的结果-因为我想用UUID字段替换User.pk是这是很正常的情况,我想很多开发人员都遇到了这个问题。我试图找到某种设置/切换来实现此目的,但无济于事,我有什么遗漏吗?

1 个答案:

答案 0 :(得分:1)

您的'UserAdmin'继承自#container { width: 960px; margin: auto; } nav { list-style-type: none; overflow: hidden; margin: 0; padding: 0; background-color: rgb(87, 222, 135, 0.3); width: 100%; } hr { margin-top: 0; border: none; background-color: black; height: 2px; width: 100%; } ,后者通过ModelAdmin方法提供了用于添加,更改,删除等视图的URL,还提供了一个“后备” URL:

get_urls

您要跟踪的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) ))), ] ,仅适合后备模式的正则表达式-它将您重定向到更改页面,以这种方式将/user/<UUID>/password/用作{{1} }。

请尝试从<UUID>/password继承,因为其object_id方法提供了所需的网址格式。


更多戳......
如果您的主键字段是一个AutoField,则整个过程将在尝试将django.contrib.auth.admin.UserAdmin中的get_urls强制转换以准备查询值时引发ValueError('invalid literal for int')。可以理解的!

如何int('some_integer/password')使用基类django.db.models.fields.AutoField.get_prep_value的{​​{1}}方法。 UUIDField只是简单地返回了值,甚至没有进行检查(毕竟,验证值应该是get_prep_value的工作)。因此,您最终得到一个查询,该查询将查找虚假的uuid Field,该伪造品显然不存在。