You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Django admin.py函数中正确调用request.user.is_superuser的方法

问题:Django Admin自定义统计字段添加request参数触发TypeError

我正在学习Django,在admin.py中编写了一个统计活动参与者数量的函数,原本运行正常。现在我想判断当前用户是否为超级用户,于是在def set_count(self, request, obj)中添加了request参数,却触发了TypeError错误。希望实现的逻辑是:如果用户是超级用户,在list_display中显示指向participants_changelist的链接;否则显示纯文本。

错误信息

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

问题原因

Django Admin在调用list_display中的自定义方法时,默认只会传递self(ModelAdmin实例)和obj(当前数据库对象)两个参数。手动添加request参数后,参数数量不匹配,触发TypeError。

要获取当前请求的用户信息,不需要把request加到方法参数里——ModelAdmin在处理请求时会自动将request赋值给自身的self.request属性,直接调用即可。

修正后的代码

from django.contrib import admin
from django.db.models import Count
from django.urls import reverse
from django.http import urlencode
from django.utils.html import format_html

class ActivityAdmin(admin.ModelAdmin):
    list_display = ['your_other_fields', 'set_count']  # 替换成你实际的字段

    def get_queryset(self, request):
        queryset = super().get_queryset(request)
        queryset = queryset.annotate(set_count=Count('activity_activity'))
        # 保存request到实例,确保后续方法能访问
        self.request = request
        return queryset

    @admin.display(description="No. of Participants", ordering="set_count")
    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="{}">{}</a>', url, counter)
        else:
            return format_html('{}', counter)

关键修正点

  1. 移除request参数:将set_count方法的参数改回self, obj,符合Django Admin的调用规范。
  2. 保存request到实例:在get_queryset方法中添加self.request = request,确保set_count能通过self.request获取当前请求。
  3. 使用@admin.display装饰器:替代手动设置short_description,同时可以指定排序字段(ordering="set_count"),让该字段支持点击排序。

内容的提问来源于stack exchange,提问作者Markmeplease

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 00:01:29