我想在Django Admin的list_display中添加“annotation count”字段。
models.py
class Log(models.Model):
...
ip_address = models.GenericIPAddressField(
verbose_name=_('IP address'),
db_index=True,
)
...
admin.py
class LogAdmin(admin.ModelAdmin):
list_display = (..., 'ip_address', 'ip_address_count', ...)
def ip_address_count(self, instance):
return models.Log.objects \
.filter(ip_address=instance.ip_address) \
.count()
ip_address_count.short_description = _('IP Address Count')
它可以很好地处理“大量”SQL查询。
我想像这样改进我的admin.py
:
class Log(models.Model):
...
def get_queryset(self, request):
qs = super(LogAdmin, self).get_queryset(request)
qs = qs.values('ip_address') \
.annotate(ip_address_count=Count('ip_address'))
return qs
def ip_address_count(self, instance):
return instance.ip_address_count
但是,我遇到了错误消息:'dict' object has no attribute '_meta'
我似乎找到了错误发生的原因:
Django Admin, can't groupe by: Exception Value: 'dict' object has no attribute '_meta'
但是,这并不能帮助我解决问题。
谢谢你的回答。
编辑:如果我不附加.values('ip_address)
,它就错误了。
它不是group by ip_address
。它group by
所有字段group by field1, field2, ip_address, ...
因此,它导致“1”所有情况。
2条答案
按热度按时间4dbbbstv1#
这就是你如何做原生。Django知道如何处理这一点(请参阅有关admin和list_display的文档)。
你可以用任何你需要的东西来注解查询集(比如
Count
)。如您所见,您只需使用相同的名称3次(在我的示例中为quantity_of_things
)1.在list_display中(Django理解这是一个可调用的),
1.在注解中,
1.在要调用的函数中。
quantity_of_things.short_description
用于列标题scyqe7ek2#
这是因为当您将
values
应用于queryset
时,它返回一个字典列表,而管理员期望的是objects
的查询集。我以前遇到过这种情况,所以我做了这样的事情:
因此,你可以看到我所做的是,从最终的查询集中获取ips,然后使用它来查询计数。通过这样做,您将在每个页面上只查询一次数据库。
我希望你得到基本的潜在的想法。请适合它根据您的需要。