在 Django Admin 中更改密码
Posted
技术标签:
【中文标题】在 Django Admin 中更改密码【英文标题】:Changing password in Django Admin 【发布时间】:2013-03-05 14:48:44 【问题描述】:我最近在 Django 项目文档中创建了 admin.py:
https://docs.djangoproject.com/en/dev/topics/auth/customizing/#django.contrib.auth.models.AbstractBaseUser
但我真的错过了允许管理员更改用户密码的功能。怎么可能添加这个功能?我只是复制并粘贴了上面链接中的代码。
from django import forms
from django.contrib import admin
from django.contrib.auth.models import Group
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.forms import ReadOnlyPasswordHashField
from customauth.models import MyUser
class UserCreationForm(forms.ModelForm):
"""A form for creating new users. Includes all the required
fields, plus a repeated password."""
password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput)
class Meta:
model = MyUser
fields = ('email', 'date_of_birth')
def clean_password2(self):
# Check that the two password entries match
password1 = self.cleaned_data.get("password1")
password2 = self.cleaned_data.get("password2")
if password1 and password2 and password1 != password2:
raise forms.ValidationError("Passwords don't match")
return password2
def save(self, commit=True):
# Save the provided password in hashed format
user = super(UserCreationForm, self).save(commit=False)
user.set_password(self.cleaned_data["password1"])
if commit:
user.save()
return user
class UserChangeForm(forms.ModelForm):
"""A form for updating users. Includes all the fields on
the user, but replaces the password field with admin's
password hash display field.
"""
password = ReadOnlyPasswordHashField()
class Meta:
model = MyUser
def clean_password(self):
# Regardless of what the user provides, return the initial value.
# This is done here, rather than on the field, because the
# field does not have access to the initial value
return self.initial["password"]
class MyUserAdmin(UserAdmin):
# The forms to add and change user instances
form = UserChangeForm
add_form = UserCreationForm
# The fields to be used in displaying the User model.
# These override the definitions on the base UserAdmin
# that reference specific fields on auth.User.
list_display = ('email', 'date_of_birth', 'is_admin')
list_filter = ('is_admin',)
fieldsets = (
(None, 'fields': ('email', 'password')),
('Personal info', 'fields': ('date_of_birth',)),
('Permissions', 'fields': ('is_admin',)),
('Important dates', 'fields': ('last_login',)),
)
add_fieldsets = (
(None,
'classes': ('wide',),
'fields': ('email', 'date_of_birth', 'password1', 'password2')
),
)
search_fields = ('email',)
ordering = ('email',)
filter_horizontal = ()
# Now register the new UserAdmin...
admin.site.register(MyUser, MyUserAdmin)
# ... and, since we're not using Django's builtin permissions,
# unregister the Group model from admin.
admin.site.unregister(Group)
[更新 - 添加信息] 我更改了以下信息,但我仍然在只读字段中看到密码(加密)。怎么可能添加链接来更改密码?
fieldsets = (
('Permissions', 'fields': ('is_active', 'is_admin','password')),
)
add_fieldsets = (
(None,
'classes': ('wide',),
'fields': ('email', 'password')
),
)
【问题讨论】:
【参考方案1】:把它放在你的 UserChangeForm 中:
password = ReadOnlyPasswordHashField(label=("Password"),
help_text=("Raw passwords are not stored, so there is no way to see "
"this user's password, but you can change the password "
"using <a href=\"../password/\">this form</a>."))
【讨论】:
嗯,有人知道为什么我在尝试访问.../user/#id/password/
时会收到 404 错误吗?我该怎么做才能为我的自定义用户模型获取此管理表单?
找到我的答案:“如果您的自定义用户模型扩展了 django.contrib.auth.models.AbstractUser,您可以使用 Django 现有的 django.contrib.auth.admin.UserAdmin 类。但是,如果您的用户模型扩展了 AbstractBaseUser,你需要定义一个自定义的 ModelAdmin 类。可以继承默认的 django.contrib.auth.admin.UserAdmin;但是,你需要覆盖任何引用字段的定义django.contrib.auth.models.AbstractUser 不在您的自定义 User 类中。”
同意。我只需要更改此行的最后一行:'using <a href=\'../password/\'>this form</a>.'
in django 1.9.1 注意“密码”之前的 ../
感谢@oskargicast 的评论,它对我的 1.9 版本有所帮助
我无法在 django 2.1 中取得成功。你还需要改变什么?【参考方案2】:
password = ReadOnlyPasswordHashField(label= ("Password"),
help_text= ("Raw passwords are not stored, so there is no way to see "
"this user's password, but you can change the password "
"using <a href=\"../password/\">this form</a>."))
href有变化,以前的django版本可以使用
<a href=\"/password/\">this form</a>
.
对于 django 1.9+
<a href=\"../password/\">this form</a>
【讨论】:
【参考方案3】:我将此方法添加到我的UserAdmin
类中:
def save_model(self, request, obj, form, change):
# Override this to set the password to the value in the field if it's
# changed.
if obj.pk:
orig_obj = models.User.objects.get(pk=obj.pk)
if obj.password != orig_obj.password:
obj.set_password(obj.password)
else:
obj.set_password(obj.password)
obj.save()
您可以正常显示密码字段,但管理员只会看到散列密码。如果他们改变了它,那么新值就会被散列并保存。
这会在您每次通过管理员保存用户时添加一个查询。这通常应该不是问题,因为大多数系统没有管理员集中编辑用户。
【讨论】:
我刚刚意识到你可以使用change
的值而不是if obj.pk
。这是留给读者的练习。 ;)
我喜欢这个解决方案,因为这意味着我不必弄乱子类化表单。您也可以使用form.changed_data
使其更加简洁。【参考方案4】:
你也可以这样做,这样你只需要覆盖字段密码,一旦你保存它,它就会为它创建哈希:
class UserModelAdmin(admin.ModelAdmin):
"""
User for overriding the normal user admin panel, and add the extra fields added to the user
"""
def save_model(self, request, obj, form, change):
user_database = User.objects.get(pk=obj.pk)
# Check firs the case in which the password is not encoded, then check in the case that the password is encode
if not (check_password(form.data['password'], user_database.password) or user_database.password == form.data['password']):
obj.password = make_password(obj.password)
else:
obj.password = user_database.password
super().save_model(request, obj, form, change)
【讨论】:
第一次创建用户时我需要捕获异常 user_database.DoesNotExist【参考方案5】:('Permissions', 'fields': ('is_active', 'is_superuser',)),
【讨论】:
你好凯瑟琳,请在问题中查看我的更新。我可以在只读字段中看到密码。但是,我不能不能选择一个新的 @Thomas 我追踪了代码,我发现密码因为这个ReadOnlyPasswordHashField()
而变成只读的。对于解决方案,您必须在密码只读字段下创建一个链接以更改密码表单【参考方案6】:
对于 django 版本独立的解决方案,您可以 reverse
UserChangeForm.__init__
中的网址,例如:
from django.core.urlresolvers import reverse
class UserChangeForm(forms.ModelForm):
password = ReadOnlyPasswordHashField()
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['password'].help_text = (
"Raw passwords are not stored, so there is no way to see "
"this user's password, but you can <a href=\"%s\"> "
"<strong>Change the Password</strong> using this form</a>."
) % reverse_lazy('admin:auth_user_password_change', args=[self.instance.id])
【讨论】:
【参考方案7】:您也可以考虑以这种方式扩展UserAdmin
:
from django.contrib import admin
from myapp.models import CustomUser
from django.contrib.auth.admin import UserAdmin
class CustomUserAdmin(UserAdmin):
list_display = []
admin.site.register(CustomUser, CustomUserAdmin)
【讨论】:
【参考方案8】:只需删除表单中输入的密码:
class MyUserChangeForm(forms.ModelForm):
# password = forms.CharField(label='Password', required=True, widget=forms.PasswordInput)
# password = ReadOnlyPasswordHashField()
class Meta:
model = CustomUser
fields = '__all__'
def save(self, commit=True):
user = super().save(commit=False)
user.set_password(self.cleaned_data["password"])
if commit:
user.save()
return user
django 3.2.8
【讨论】:
正如目前所写,您的答案尚不清楚。请edit 添加其他详细信息,以帮助其他人了解这如何解决所提出的问题。你可以找到更多关于如何写好答案的信息in the help center。以上是关于在 Django Admin 中更改密码的主要内容,如果未能解决你的问题,请参考以下文章