使用 Django admin 的自定义列
Posted
技术标签:
【中文标题】使用 Django admin 的自定义列【英文标题】:Custom columns using Django admin 【发布时间】:2012-02-28 04:38:39 【问题描述】:我有一个模型 Data
,关联到这样的表(模型 Data
仅由 IntegerField 组成):
subject | year | quarter | sales |
----------------------------------
1 | 2010 | 1 | 20 |
1 | 2010 | 2 | 100 |
1 | 2010 | 3 | 100 |
1 | 2010 | 4 | 20 |
1 | 2011 | 1 | 30 |
1 | 2011 | 2 | 50 |
1 | 2011 | 4 | 40 |
2 | 2010 | 1 | 30 |
2 | 2010 | 2 | 20 |
[..-GO ON this way...]
我想要一个 django-admin 表,只读有列 (current year = 2011, quarter = 1
)
subject | sales current year | sales current quarter | sales last year | sales current quarter last year |
----------------------------------------------------------------------------------------------------------
1 | 110 | 30 | 240 | 20
[AND SO ON]
问题是:使用 django-admin 可以做到吗?出路是什么?
【问题讨论】:
【参考方案1】:这样的东西应该可以工作(未经测试):
# models.py
class Data(models.Model):
year = models.DateField()
sales = models.IntegerField()
# ...
def sales_current_year(self):
return self.model._default_manager.get_queryset().filter(year=2012).annotate(Sum('sales'))
# admin.py
class DataAdmin(admin.ModelAdmin):
list_display = ('sales_current_year',)
【讨论】:
【参考方案2】:您可以使用Model
或ModelAdmin
上的方法作为list_display
的项目。见:https://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.list_display
由于这些方法在管理员之外也可能有用,我建议将它们添加到您的Model
。
from django.db.models import Sum
class Data(models.Model):
...
# Method used by `get_current_year_sales` and `get_last_year_sales`
# to stay DRY. Not for use directly in admin.
def get_year_sales(self, year):
qs = self.model._default_manager.filter(year=year)
sales_agg = qs.aggregate(Sum('sales'))
return sales_agg['sales__sum']
# Method used by `get_current_quarter_sales` and `get_last_quarter_sales`
# to stay DRY. Not for use directly in admin.
def get_quarter_sales(self, year, quarter):
qs = self.model._default_manager.filter(year=year, quarter=quarter)
sales_agg = qs.aggregate(Sum('sales'))
return sales_agg['sales__sum']
def get_current_year_sales(self):
return self.get_year_sales(datetime.now().year)
get_current_year_sales.short_description = 'Sales (Current Year)'
def get_last_year_sales(self):
return self.get_year_sales(datetime.now().year-1)
get_last_year_sales.short_description = 'Sales (Last Year)'
def get_current_quarter_sales(self):
# Determine current quarter logic here as `current_quarter`
# `quarter_year` will likely be same as current year here,
# but will need to be calculated for previous quarter
return self.get_quarter_sales(quarter_year, current_quarter)
get_current_quarter_sales.short_description = 'Sales (Current Quarter)'
def get_current_quarter_sales(self):
# Logic here to determine last quarter as `last_quarter`
# Logic to determine what year last quarter was in as `quarter_year`
return self.get_quarter_sales(quarter_year, last_quarter)
get_last_quarter_sales.short_description = 'Sales (Last Quarter)'
short_description
属性决定管理员将在这些方法的行标题中显示的内容。因此,一旦您完成了所有这些,您只需修改您的 ModelAdmin
的 list_display
属性,例如:
class DataAdmin(admin.ModelAdmin):
...
list_display = ('subject', 'get_current_year_sales', 'get_last_year_sales', 'get_current_quarter_sales', 'get_last_quarter_sales')
【讨论】:
最后一个问题,如果我想对列进行排序,它不起作用,因为这些是方法而不是属性,对吗?谢谢! 查看this和this 是的。您可以通过告诉 django 与<method>.admin_order_field = 'my_field'
一起使用哪个字段来添加排序功能,但在这种情况下并没有一个很好的字段可以将其绑定。
如果新列没有出现,请尝试重新启动 Django 服务器。
如何为这个自定义字段'get_current_year_sales'设置标签,例如'Current Year Sale' w/o 'get'?以上是关于使用 Django admin 的自定义列的主要内容,如果未能解决你的问题,请参考以下文章
django admin changelist_view 中的自定义 html 字段
基于列表显示中的自定义可调用在 Django Admin 中排序