The solutions above works if the field is nullable. Using render_value
will render the password into the input field and show the value as asterix placeholders.
Attention: This is great if you simply want to hide the password from users, but the password will be readable by using javascript.
class UserForm(forms.ModelForm):
class Meta:
model = Org
fields = '__all__'
widgets = {
'password': forms.PasswordInput(render_value=True),
}
Edit:
Found a better solution without exposing the current password.
PASSWORD_ASTERIX_PLACEHOLDER
will be set as value when loading the input. Before saving the model, it reverts the value to the old one if a user is not setting an explicit new password.
FormInput:
class PrefilledPasswordInput(PasswordInput):
PASSWORD_ASTERIX_PLACEHOLDER: str = 'hidden-password'
def __init__(self, attrs: dict = None, *args, **kwargs):
if not attrs:
attrs = {}
attrs.setdefault('value', PrefilledPasswordInput.PASSWORD_ASTERIX_PLACEHOLDER)
super().__init__(attrs=attrs, *args, **kwargs)
ModelField:
class PasswordCharField(models.CharField):
def to_python(self, value):
return super().to_python(value)
def pre_save(self, model_instance, add):
attr_name = self.get_attname()
if not add:
# Reset to old value if matching with PASSWORD_ASTERIX_PLACEHOLDER
old_instance = self.model.objects.get(id=model_instance.id)
current_value: str = getattr(model_instance, attr_name)
if current_value == PrefilledPasswordInput.PASSWORD_ASTERIX_PLACEHOLDER:
old_value: str = getattr(old_instance, attr_name)
setattr(model_instance, attr_name, old_value)
return super().pre_save(model_instance, add)
Your admin-(form):
class UserForm(forms.ModelForm):
class Meta:
model = Org
fields = '__all__'
widgets = {
'password': PrefilledPasswordInput(),
}
Your model:
class User(SomeBaseModel):
...
password = PasswordCharField(max_length=32, null=False, blank=False)