ReadOnly username for the 'admin' user

Hi,

I customized the user model with inheriting the AbstractUser.

I want all the users to have the username editable, except the user which has the username ‘admin’.

I wanted to create two user model (one for the common users and another one for the admin) but Django only accepts one model.

Do you have a solution on how to have the user admin with readonly username field ?

I could prevent the username from being edited using permissions on my views, but I think it’s more secure and strong to do it directly on the database.

Thanks for your help.

You should solve this in your form’s __init__ method instead, conditionally making the field editable.

For example (untested):

class MyUserForm(...):
    ...
    def __init__(self, *args, **kwargs):
         super().__init__(*args, **kwargs)
         self.fields['username'].disabled = (self.instance.is_superuser)
2 Likes

Are you talking about doing this within the Django Admin, or within your own forms?

If you’re talking about doing this within the Admin facility, you could try implementing your own get_readonly_fields that checks to see if the current user is admin, and if so, returning the username field.

Regarding your other statement about security, yes, there is a potential issue, depending upon usage of your database. But if your Django app is the only application using this database, it’s much less an issue. If you have control over the application layer, it’s quite common to manage access on that layer and not try to push that management back on to the database. (There’s an argument to be made that keeping all access controls in the same layer is more secure, since you don’t have to account for any interactions or gaps between layers.)

Ken

Many thanks for your help.

From what I understand it’s not possible to implement it on the database side.

You should solve this in your form’s __init__ method instead, conditionally making the field editable.

For example (untested):

class MyUserForm(...):
    ...
    def __init__(self, *args, **kwargs):
         super().__init__(*args, **kwargs)
         self.fields['username'].disabled = (self.instance.is_superuser)

Since I am using Djang Rest Framework I think I have to find the equivalent of your code in my User serializer code. I will try to find a solution in that way (if you have also have this precious piece of code that would be great :slight_smile: )

adamchainz, your code is Great.

Actually it also works just fine with my serializer, thanks !