开发者

Understanding Python Classes or Customising the Django UserAdmin model

I'm attempting to override some of the behaviour of the Django UserAdmin model. Particularly, I'd like to hide the 'superuser' field from non-superusers.

So, my approach is this:

class ModelAdmin(BaseModelAdmin):
    "Encapsulates all admin options and functionality for a given model."

    # ...

    def has_change_permission(self, request, obj=No开发者_如何学Cne):
        """
        Returns True if the given request has permission to change the given
        Django model instance.

        If `obj` is None, this should return True if the given request has
        permission to change *any* object of the given type.
        """
        opts = self.opts
        return request.user.has_perm(opts.app_label + '.' + opts.get_change_permission())

    #...

Based on what I've found in ModelAdmin

class UserAdmin(UserAdmin):
    """
    ... my customised UserAdmin
    """

    # adding a new method
    def is_superuser(self, request):
        "Returns True if the given user is a superuser."
        return request.user.is_superuser

    # then elsewhere 'hopefully' show a slightly different fieldset
    # the following, of course, doesn't work.

    fieldsets = (
        (None, {
            'fields': (
                ("first_name", "last_name"), 
                ("email", "password"), 
                "is_staff", 
                "is_active", 
                "is_superuser" if self.is_superuser() else None

            )   
        }),
        ('Groups', {
            'fields': (
                'groups', 
            )
        }),
        ('Meta', {
            'classes': ('collapse',),
            'fields': (
                'username',
                "last_login", 
                "date_joined"
            )
        })
    )

So, my questions are:

  • How do I create a def within my new custom UserAdmin class, such as above, and how do I call it? (How do I know when I'm in the right context to do so)
  • Part 2 (bonus): how can I succinctly include/exclude the 'is_superuser' field in the form, as the psuedo code above is suggesting?

Kind thanks fellows!

~ Daryl

Thank you


If you just want to forbid users to promote themselves to superuser, override YourUserAdmin.get_readonly_fields():

class YourUserAdmin(admin.ModelAdmin):
    ...
    def get_readonly_fields(self, request, obj=None):
        if request.user.is_superuser:
            return None
        try:
            return self.readonly_fields + ('is_superuser',)
        except:
            return ('is_superuser',)

You have to unregister the default User/UserAdmin and then register your own.

admin.site.unregister(User)
admin.site.register(User, YourUserAdmin)

However, the ZEN of admin says:

At it's core, Django's admin is designed for a single activity: trusted users editing structured content.

If the user is not trusted, do not give him edit rights to edit user accounts, period. Even if you hide the superadmin option and the "filter by superadmin status" filter, he can just change your password and log in as you. So, if you need some untrusted users to edit user accounts, forget the admin and write your own dumbed down interface.


No experience with Django but thinking a closure might help you in this situation:

class UserAdmin(UserAdmin):

    # adding a new method
    def is_superuser(self, request):
        "Returns True if the given user is a superuser."
        return request.user.is_superuser

    def gen_fieldset(self, request):
        '''
        If request.user.is_supeuser == true then return fieldset generator for superuser.
         Else return fieldset generator for normal user.
         ''' 
        su = is_superuser(request)
        def get_fieldset():
            if su:
                return super_user_fieldset
            else:
                return normal_user_fieldset
        return get_fieldset

Usage would go like this:

obj = UserAdmin()
request = ... #Generate a normal or super-user request.
fieldset = obj.gen_fieldset(request)
# Sometime later when you want to use the fieldset...
fields = fieldset() # Function will decide which fieldset to give based on gen_fieldset() call earlier.

So the basic idea is that you can configure get_fieldset() ahead of time (via the call to gen_fieldset() where the closure is employed) to return the appropriate fieldset for the user's level. Give the user the function object returned by gen_fieldset() it'll generate the appropriate fieldset at a later time whenever the user calls it.

NOTE: If you've never used closures before I'd suggest googling around for other examples and use scenarios. There may be other solutions that'll fit your situation better (again, not familiar with Django) but that was the first thing that came to my mind.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜