简体   繁体   English

Django admin 中用于计算字段的自定义过滤器

[英]Custom filter in Django admin for calculated fields

# models.py

class Author(models.Model):
   name = models.CharField(max_length=50)

class Book(models.Model):
   title = models.CharField(max_length=50)
   created_time = models.DateTimeField(auto_now=False, auto_now_add=True)
   writer = models.ForeignKey(Author, on_delete=models.CASCADE, related_name='books')

# admin.py

@admin.register(Author)
class AuthorAdmin(admin.ModelAdmin):

    def get_queryset(self, request):
        qs = super(AuthorAdmin, self).get_queryset(request)
        return qs.annotate(books_count=Count('books'))

    def books_count(self, inst):
        return inst.books_count

    list_display = ['author', 'books_count']

Now I have two columns in admin: Author and Books count .现在我在 admin 中有两列: AuthorBooks count

I need to add DateFieldListFilter , but for a calculated field (not for model field).我需要添加DateFieldListFilter ,但对于计算字段(而不是模型字段)。

For example, to have a possibility show created books count by each author for last_week , last_month , last_year , etc.例如,要显示每个作者为last_weeklast_monthlast_year等创建的书籍计数的可能性。

Old question, and you've likely found the answer already, but I literally just did this today (mostly) - I don't think you'd be able to get a count with a filter, as that's not really what a filter does in Django admin;老问题,您可能已经找到了答案,但我今天(主要是)确实做到了这一点-我认为您无法使用过滤器进行计数,因为过滤器实际上不是这样做的在 Django 管理员中; but the quantity of results that have been returned with the filter/s applied does show on the page already但是应用过滤器返回的结果数量确实显示在页面上

From what I've found, Calculated Fields can be used with list_display in your ModelAdmin - exactly as you've done with books_count根据我的发现,计算字段可以与ModelAdmin 中的list_display一起使用 - 与您对books_count所做的完全一样

But to create a custom Filter , you have to use a subclass and work with queries instead;但是要创建自定义Filter ,您必须使用子类并使用查询; which makes sense if you think about the inner workings of what's going on如果你考虑正在发生的事情的内部运作,这是有道理的

Hopefully someone finds this useful!希望有人觉得这很有用!

from django.contrib import admin
from datetime import datetime, timedelta

class DateFieldListFilter(admin.SimpleListFilter):
    title = 'Book Count Filter'
    parameter_name = 'books_count'

    def lookups(self, request, model_admin):
        return (
            ('last_week', 'Last Week'),
            ('last_month', 'Last Month'),
            ('last_year', 'Last Year'),
        )

    def queryset(self, request, queryset):
        value = self.value()
        today = datetime.today().date()

        if value == 'last_week':
            start_date = today - timedelta(days=7)
            return queryset.filter(created__gte=start_date)
        elif value == 'last_month':
            start_of_month = today.replace(day=1)
            end_of_last_month = start_of_month - timedelta(days=1)
            start_date = end_of_last_month.replace(day=today.day)
            return queryset.filter(created__gte=start_date)
        elif value == 'last_year':
            start_date = today.replace(year=today.year - 1)
            return queryset.filter(created__gte=start_date)

        return queryset

@admin.register(Author)
class AuthorAdmin(admin.ModelAdmin):
    list_display = ['author', 'books_count']
    list_filter = (DateFieldListFilter,)

    def get_queryset(self, request):
        qs = super(AuthorAdmin, self).get_queryset(request)
        return qs.annotate(books_count=Count('books'))

    def books_count(self, inst):
        return inst.books_count

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM