menu

Questions & Answers

How properly request.user.is_superuser inside function in django admin.py

I am learning Djnago and I have this function inside admin.py that counts how many participants in an activity, it is working fine until, I want to know if the current user is a superuser and added request inside def set_count(self, request, obj) expecting to make a request for the user. Since I am getting an error, this means, this it's not how to do it and wrong. How to correct this? Thanks.

Below is what I want to do, evaluate the user.is_superuser if true, it will display in the list_display the link to the participants_changelist otherwise, display a plain text.

def get_queryset(self, request):
    queryset = super().get_queryset(request)
    queryset = queryset.annotate(set_count=Count('activity_activity'))
    return queryset

def set_count(self, request, obj):
    
    counter =  obj.set_count
    if request.user.is_superuser:
        
        url = (
            reverse("admin:activity_announcements_participants_changelist")
            + "?"
            + urlencode({"activity__id": f"{obj.id}"})
        )
    
        return format_html('<a href="{}">{} Paticipants</a>', url, counter)
    else:
        counter =  obj.set_count
        return format_html('{} Paticipants', counter)

set_count.short_description = "No. of Paticipants"

Error:

TypeError at /admin/activity_announcements/activity/
ActivityAdmin.set_count() missing 1 required positional argument: 'obj'
Request Method: GET
Request URL:    http://localhost:8000/admin/activity_announcements/activity/
Django Version: 4.1.5
Exception Type: TypeError
Exception Value:    
ActivityAdmin.set_count() missing 1 required positional argument: 'obj'
Exception Location: /py/lib/python3.11/site-packages/django/contrib/admin/utils.py, line     280, in lookup_field
Raised during:  reversion.admin.changelist_view
Python Executable:  /py/bin/python
Python Version: 3.11.1
Python Path:    
['/app',
'/usr/local/lib/python311.zip',
'/usr/local/lib/python3.11',
'/usr/local/lib/python3.11/lib-dynload',
'/py/lib/python3.11/site-packages',
'/py/lib/python3.11/site-packages/odf',
'/py/lib/python3.11/site-packages/odf',
'/py/lib/python3.11/site-packages/odf',
'/py/lib/python3.11/site-packages/odf',
'/py/lib/python3.11/site-packages/odf',
'/py/lib/python3.11/site-packages/odf',
'/py/lib/python3.11/site-packages/odf']
Server time:    Sun, 22 Jan 2023 03:06:22 +0800
Answers(1) :

The problem is that when defining a custom field to list in the admin, you don't have access to the request. The function definition should be like this def your_field(self, obj): . In order to get the request in a field definition you can do the following:

    class YourAdmin(admin.modeladmin):
        def get_queryset(self, request):
            self.request = request
            return super().get_queryset(request)

    def set_count(self, obj):
    
        counter =  obj.set_count

        if self.request.user.is_superuser:
        
            url = (
            reverse(
             "admin:activity_announcements_participants_changelist")
             + "?"
             + urlencode({"activity__id": f"{obj.id}"})
            )
    
            return format_html('<a href="{}">{} Participants</a>', url, counter)
        else:
            counter =  obj.set_count
        return format_html('{} Participants', counter)
    set_count.short_description = "No. of Paticipants"