Django admin UserChangeForm,UUID字段为主键



我正在开发一个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定义中的admin-url配置,但我想知道是否有更简单的方法来实现所需的结果——因为我认为用UUID字段替换User.pk是一种相当常见的情况,我认为许多开发人员都遇到了这个问题。我试图找到某种设置/切换来实现这一点,但没有成功,我是不是错过了什么?

您的"UserAdmin"继承自ModelAdmin,它通过get_urls方法为添加、更改、删除等视图提供url,但也提供了一个"回退"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/,它只适合回退模式的regex,它将您重定向到更改页面,并使用<UUID>/password作为object_id

尝试从django.contrib.auth.admin.UserAdmin继承,因为它的get_urls方法提供了您需要的url模式。


还有一些人四处窥探
如果主键字段是AutoField,则在django.db.models.fields.AutoField.get_prep_value中尝试强制转换int('some_integer/password')以准备查询值时,整个过程将引发ValueError('invalid literal for int')。可以理解!

HOWEVER:UUIDField使用基类Fieldget_prep_value方法。Field.get_prep_value只是简单地返回值,甚至不进行检查(毕竟,验证值应该是UUIDField的工作(。因此,您最终会得到一个查询,该查询查找伪造的uuid'<uuid>/password',而该uuid显然不存在。

最新更新