在Django管理站点中,当我编辑其他小部件的属性时,密码字段会更改。

huangapple go评论58阅读模式
英文:

In Django Admin site password field changes when I edit the attribute of other widgets

问题

在默认的Django管理站点中,"Password"字段显示加密方式,并提供更改密码的链接。

在我的项目中,我需要将一些字段设置为从左到右(LTR),因为该站点是从右到左(RTL)的。这是我所做的:

from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.utils.translation import gettext_lazy as _
from django import forms

from .models import CustomUser

# 在这里注册您的模型

class CustomUserForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['email'].widget.attrs.update({'dir': 'ltr'})
        self.fields['national_id'].widget.attrs.update({'dir': 'ltr'})
        self.fields['mobile_number'].widget.attrs.update({'dir': 'ltr'})

@admin.register(CustomUser)
class CustomUserAdmin(UserAdmin):
    form = CustomUserForm
    # 其他配置选项...

但是使用这个自定义表单后,"Password"字段看起来是这样的:

我没有改动与此相关的任何内容。为什么会发生这种变化?

编辑:

如您所请求,这是自定义用户模型:

from django.db import models
from django.contrib.auth.models import BaseUserManager, AbstractUser
from django.contrib.auth.hashers import make_password
from django.utils.translation import gettext_lazy as _

# 创建您的模型

class CustomUserManager(BaseUserManager):
    use_in_migrations = True

    def _create_user(self, email, password, **extra_fields):
        """
        创建并保存具有给定电子邮件和密码的用户
        """
        if not email:
            raise ValueError('必须设置电子邮件')

        email = self.normalize_email(email)
        user = self.model(email=email, **extra_fields)
        user.password = make_password(password)
        user.save(using=self._db)
        return user

    def create_user(self, email, password=None, **extra_fields):
        extra_fields.setdefault('is_staff', False)
        extra_fields.setdefault('is_superuser', False)
        return self._create_user(email, password, **extra_fields)

    def create_superuser(self, email, password=None, **extra_fields):
        extra_fields.setdefault('is_staff', True)
        extra_fields.setdefault('is_superuser', True)

        if extra_fields.get('is_staff') is not True:
            raise ValueError('超级用户必须具备 is_staff=True。')
        if extra_fields.get('is_superuser') is not True:
            raise ValueError('超级用户必须具备 is_superuser=True。')

        return self._create_user(email, password, **extra_fields)

class CustomUser(AbstractUser):
    username = None
    email = models.EmailField(_('电子邮件地址'), unique=True)
    is_verified = models.BooleanField(
        _('已验证状态'),
        blank=True,
        default=False,
        help_text=_('指示用户是否已验证其电子邮件地址。'),
    )

    national_id = models.CharField(
        _('国民身份证'),
        max_length=10,
        unique=True,
        blank=True,
        null=True,
        help_text=_('10位国民身份证号码'),
    )

    mobile_number = models.CharField(
        '手机号码',
        max_length=13,
        unique=True,
        blank=True,
        null=True,
        help_text='包括国家代码(+98)的13位手机号码',
    )

    home_address = models.TextField(
        '家庭地址',
        blank=True,
    )

    work_address = models.TextField(
        '工作地址',
        blank=True,
    )

    objects = CustomUserManager()

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = []

    class Meta:
        verbose_name = _('用户')
        verbose_name_plural = _('用户')
        permissions = (('can_verify_user', _('可以验证用户')),)

无论是否使用自定义表单,其他所有内容都与Django的默认管理站点完全相同。只有"Password"字段发生了变化。

英文:

In the default Django Admin site, the Password field shows how it is encrypted and there's a link to change it.

在Django管理站点中,当我编辑其他小部件的属性时,密码字段会更改。

In my project I need to set some fields to LTR (because the site is in RTL), so this is what I do:

from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.utils.translation import gettext_lazy as _
from django import forms
from .models import CustomUser
# Register your models here.
class CustomUserForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['email'].widget.attrs.update({'dir': 'ltr'})
self.fields['national_id'].widget.attrs.update({'dir': 'ltr'})
self.fields['mobile_number'].widget.attrs.update({'dir': 'ltr'})
@admin.register(CustomUser)
class CustomUserAdmin(UserAdmin):
form = CustomUserForm
fieldsets = (
(None, {'fields': ('email', 'password')}),
(
_('Personal info'),
{
'fields': (
'first_name',
'last_name',
)
},
),
(
_('Profile info'),
{
'fields': (
'national_id',
'mobile_number',
'home_address',
'work_address',
)
},
),
(
_('Permissions'),
{
'fields': (
'is_active',
'is_staff',
'is_superuser',
'is_verified',
'groups',
'user_permissions',
),
},
),
(_('Important dates'), {'fields': ('last_login', 'date_joined')}),
)
add_fieldsets = (
(
None,
{
'classes': ('wide',),
'fields': ('email', 'password1', 'password2'),
},
),
)
list_display = ('email', 'first_name', 'last_name', 'is_staff')
list_filter = ('is_staff', 'is_superuser', 'is_active', 'groups')
search_fields = ('email', 'first_name', 'last_name', 'national_id', 'mobile_number')
ordering = ('email',)
filter_horizontal = (
'groups',
'user_permissions',
)

But with that custom form, the Password field looks like this:

在Django管理站点中,当我编辑其他小部件的属性时,密码字段会更改。

I have not touched anything related to it. Why it is changing?

EDIT:

As requested, here's the custom user model:

from django.db import models
from django.contrib.auth.models import BaseUserManager, AbstractUser
from django.contrib.auth.hashers import make_password
from django.utils.translation import gettext_lazy as _
# Create your models here.
class CustomUserManager(BaseUserManager):
use_in_migrations = True
def _create_user(self, email, password, **extra_fields):
"""
Create and save a user with the given email and password
"""
if not email:
raise ValueError('The given email must be set')
email = self.normalize_email(email)
user = self.model(email=email, **extra_fields)
user.password = make_password(password)
user.save(using=self._db)
return user
def create_user(self, email, password=None, **extra_fields):
extra_fields.setdefault('is_staff', False)
extra_fields.setdefault('is_superuser', False)
return self._create_user(email, password, **extra_fields)
def create_superuser(self, email, password=None, **extra_fields):
extra_fields.setdefault('is_staff', True)
extra_fields.setdefault('is_superuser', True)
if extra_fields.get('is_staff') is not True:
raise ValueError('Superuser must have is_staff=True.')
if extra_fields.get('is_superuser') is not True:
raise ValueError('Superuser must have is_superuser=True.')
return self._create_user(email, password, **extra_fields)
class CustomUser(AbstractUser):
username = None
email = models.EmailField(_('email address'), unique=True)
is_verified = models.BooleanField(
_('verified status'),
blank=True,
default=False,
help_text=_('Designates whether this user has verified their email address.'),
)
national_id = models.CharField(
_('National ID'),
max_length=10,
unique=True,
blank=True,
null=True,
help_text=_('10-digit National ID number'),
)
mobile_number = models.CharField(
'Mobile Number',
max_length=13,
unique=True,
blank=True,
null=True,
help_text='13-digit mobile number including country code (+98)',
)
home_address = models.TextField(
'home address',
blank=True,
)
work_address = models.TextField(
'work address',
blank=True,
)
objects = CustomUserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
class Meta:
verbose_name = _('user')
verbose_name_plural = _('users')
permissions = (('can_verify_user', _('Can verify user')),)

With or without that custom form, everything else looks exactly the same as Django's default Admin site. It is only the Password field that changes.

答案1

得分: 1

这是因为您正在使用CustomUserForm覆盖默认的User Admin表单。如果您想处理这种情况,您也必须在您的表单中处理密码字段,就像这样:

from django.contrib.auth.forms import ReadOnlyPasswordHashField

class CustomUserForm(forms.ModelForm):
    password = ReadOnlyPasswordHashField(
        label="密码",
        help_text=(
            "原始密码不会被存储,因此无法查看此用户的密码,但您可以使用<a href=\"../password/\">此表单</a>更改密码。"
        ),
    )
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['email'].widget.attrs.update({'dir': 'ltr'})
        self.fields['national_id'].widget.attrs.update({'dir': 'ltr'})
        self.fields['mobile_number'].widget.attrs.update({'dir': 'ltr'})

    class Meta:
        model = CustomUser
        fields = '__all__'

请注意,我已经将HTML实体(如&quot;&lt;)翻译回了相应的字符。

英文:

It is because you are overriding default User Admin form with CustomUserForm. If you want to handle this situation you have to handle password field in your form too like this:

from django.contrib.auth.forms import ReadOnlyPasswordHashField

class CustomUserForm(forms.ModelForm):
    password = ReadOnlyPasswordHashField(
        label=(&quot;Password&quot;),
        help_text=(
            &quot;Raw passwords are not stored, so there is no way to see &quot;
            &quot;this user&#39;s password, but you can change the password &quot;
            &quot;using &lt;a href=\&quot;../password/\&quot;&gt;this form&lt;/a&gt;.&quot;
        ),
    )
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields[&#39;email&#39;].widget.attrs.update({&#39;dir&#39;: &#39;ltr&#39;})
        self.fields[&#39;national_id&#39;].widget.attrs.update({&#39;dir&#39;: &#39;ltr&#39;})
        self.fields[&#39;mobile_number&#39;].widget.attrs.update({&#39;dir&#39;: &#39;ltr&#39;})

    class Meta:
        model = CustomUser
        fields = &#39;__all__&#39;

huangapple
  • 本文由 发表于 2023年7月3日 18:23:43
  • 转载请务必保留本文链接:https://go.coder-hub.com/76603855.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定