按Null/Is Not Nu筛选Django Admin

2024-04-29 15:17:00 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个简单的Django模型,比如:

class Person(models.Model):
    referrer = models.ForeignKey('self', null=True)
    ...

在这个模型的ModelAdmin中,如何根据referer是否为空来过滤它?默认情况下,将referer添加到list_filter会显示一个下拉列表,其中列出每个人记录(可能有成百上千条记录),从而有效地防止页面加载。即使它加载了,我仍然无法按我想要的标准进行筛选。

也就是说,我该如何修改它,以便下拉列表只列出“All”、“Null”或“Not Null”选项?

我见过一些posts声称使用自定义FilterSpec子类来完成类似的任务,但没有一个解释如何使用它们。我见过的少数几个应用于所有模型中的所有字段,这是我不想要的。此外,还有FilterSpec的zero文档,这让我很紧张,因为我不想投资于绑定到某个可能在下一个版本中消失的临时内部类的大量自定义代码。


Tags: django模型self列表modelmodels记录null
3条回答

有一个简单的方法:

class RefererFilter(admin.SimpleListFilter):
    title = 'has referer'
    # Parameter for the filter that will be used in the URL query.
    parameter_name = 'referer__isnull'

    def lookups(self, request, model_admin):
        return (
            ('False', 'has referer'),
            ('True', 'has no referer'),
        )

    def queryset(self, request, queryset):
        if self.value() == 'False':
            return queryset.filter(referer__isnull=False)
        if self.value() == 'True':
            return queryset.filter(referer__isnull=True)

然后在ModelAdmin中使用它们:

class PersonAdmin(admin.ModelAdmin):
    list_filter =  (RefererFilter,) 

由于Django 1.4给过滤器带来了一些变化,我想我节省了一些时间,我只是花在修改Cerin接受的答案中的代码来使用django1.4rc1。

我有一个名为“started”的TimeField(null=True)模型,我想过滤空值和非空值,所以这和OP的问题很相似。
所以,这是对我有用的。。。

在admin.py中定义(实际包括)这些:

from django.contrib.admin.filters import SimpleListFilter

class NullFilterSpec(SimpleListFilter):
    title = u''

    parameter_name = u''

    def lookups(self, request, model_admin):
        return (
            ('1', _('Has value'), ),
            ('0', _('None'), ),
        )

    def queryset(self, request, queryset):
        kwargs = {
        '%s'%self.parameter_name : None,
        }
        if self.value() == '0':
            return queryset.filter(**kwargs)
        if self.value() == '1':
            return queryset.exclude(**kwargs)
        return queryset



class StartNullFilterSpec(NullFilterSpec):
    title = u'Started'
    parameter_name = u'started'

而不仅仅是在ModelAdmin中使用它们:

class SomeModelAdmin(admin.ModelAdmin):
    list_filter =  (StartNullFilterSpec, )

我有一个更简单的frnhr答案,它实际上过滤了__isnull条件。 (Django 1.4+):

from django.contrib.admin import SimpleListFilter

class NullListFilter(SimpleListFilter):
    def lookups(self, request, model_admin):
        return (
            ('1', 'Null', ),
            ('0', '!= Null', ),
        )

    def queryset(self, request, queryset):
        if self.value() in ('0', '1'):
            kwargs = { '{0}__isnull'.format(self.parameter_name) : self.value() == '1' }
            return queryset.filter(**kwargs)
        return queryset

然后还:

class StartNullListFilter(NullListFilter):
    title = u'Started'
    parameter_name = u'started'

最后:

class SomeModelAdmin(admin.ModelAdmin):
    list_filter =  (StartNullListFilter, )

我个人不喜欢用几十个类来破坏我的admin.py,所以我提出了这样一个helper函数:

def null_filter(field, title_=None):
    class NullListFieldFilter(NullListFilter):
        parameter_name = field
        title = title_ or parameter_name
    return NullListFieldFilter

我以后可以申请如下:

class OtherModelAdmin(admin.ModelAdmin):
    list_filter =  (null_filter('somefield'), null_filter('ugly_field', _('Beautiful Name')), )

相关问题 更多 >