在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)
关键修正点
- 移除request参数:将
set_count方法的参数改回self, obj,符合Django Admin的调用规范。 - 保存request到实例:在
get_queryset方法中添加self.request = request,确保set_count能通过self.request获取当前请求。 - 使用@admin.display装饰器:替代手动设置
short_description,同时可以指定排序字段(ordering="set_count"),让该字段支持点击排序。
内容的提问来源于stack exchange,提问作者Markmeplease
相关产品推荐
相关产品推荐

