有表格Product
和Transaction
。在Product
admin中,有一个字段显示已使用此产品创建了多少交易。
现在,我想过滤创建这些事务的时间段。例如,上周有30笔交易,但上个月有100笔交易。
class Transaction(models.Model):
created = models.DateTimeField()
product = models.ForeignKey('Product')
class Product(models.Model):
name = models.CharField()
def num_of_trans(self):
return Transaction.objects.filter(created="""DATE_VALUE_HERE""").filter(product=self.id).count()
我尝试在queryset
扩展的类中调整SimpleListFilter
,但是我无法使其正常工作。
我想到的另一件事是向num_of_trans
函数添加一个额外的参数,但似乎在使用过滤器时无法传递此参数。
我很感激任何提示。
修改
class MyListFilter(admin.SimpleListFilter):
title = _('period')
parameter_name = 'period'
def lookups(self, request, model_admin):
return (
('7', _('last week')),
('30', _('last month')),
)
def queryset(self, request, queryset):
period = timezone.now() + timedelta(days=self.value()))
return queryset.filter(transactions__gte=period)
# of course it won't work, but represents the idea
答案 0 :(得分:0)
from datetime import datetime, timedelta
class Transaction(models.Model):
created = models.DateTimeField()
product = models.ForeignKey('Product', related_name='products')
class Product(models.Model):
name = models.CharField()
def num_of_trans_last_week(self):
now = datetime.now()
self.products.filter(created__range=(now-timedelta(days=7), now)).count()
答案 1 :(得分:0)
虽然我尽量不使用带有ORM的纯SQL,但在这种情况下使用“extra”是我能想到的唯一方法。进行2次额外查询。
class MyListFilter(admin.SimpleListFilter):
title = _('period')
parameter_name = 'period'
def lookups(self, request, model_admin):
return (
('7', _('last week')),
('30', _('last month')),
)
def queryset(self, request, queryset):
if self.value(): # Count transactions by date
period = timezone.now() - timedelta(days=int(self.value())
transaction_ids = Transaction.objects\
.filter(created__gte=period)\
.values_list('id', flat=True)
qs = queryset.extra(select={
"num_transactions": """
SELECT COUNT(*)
FROM appname_transaction
WHERE appname_transaction.id IN ({})
AND appname_transaction.product_id = appname_product.id
""".format(", ".join([str(t_id) for t_id in transaction_ids]))
})
else: # Count all
qs = queryset.extra(select={
"num_transactions": """
SELECT COUNT(*)
FROM appname_transaction
WHERE appname_transaction.product_id = appname_product.id
"""
})
return qs
class ProductAdmin(admin.ModelAdmin):
list_filter = [MyListFilter, ]
list_display = [..., 'num_transactions']
...
def num_transactions(self, obj):
return getattr(obj, 'num_transactions')