Django admin list_filter - 过滤字段为空(无或空字符串“”)

时间:2016-06-13 21:48:58

标签: django django-admin

在models.py中我有:

class User(modals.Model):
    name = models.CharField(max_length=255)
    image = models.ImageField(blank=True, null=True)

在admin.py中:

class UserAdmin(admin.ModelAdmin):
    list_filter = ['image']

admin.site.register(User, UserAdmin)

我只是想通过拥有图像来过滤用户(空或空字符串)

但是django显示按图片urls =)

过滤

有没有办法让list_filter = ['image']表现得像布尔字段?

建议的大问题!

5 个答案:

答案 0 :(得分:14)

admin.py

l_i

答案 1 :(得分:5)

从 Django 3.1 开始,您可以使用 class button(): def __init__(self, color, x,y,width,height, text=''): self.color = color self.x = x self.y = y self.width = width self.height = height self.text = text def draw(self,win,outline=None): #Call this method to draw the button on the screen if outline: pygame.draw.rect(win, outline, (self.x-2,self.y-2,self.width+4,self.height+4),0) pygame.draw.rect(win, self.color, (self.x,self.y,self.width,self.height),0) if self.text != '': font = pygame.font.SysFont('comicsans', 60) text = font.render(self.text, 1, (0,0,0)) win.blit(text, (self.x + (self.width/2 - text.get_width()/2), self.y + (self.height/2 - text.get_height()/2))) def isOver(self, pos): #Pos is the mouse position or a tuple of (x,y) coordinates if pos[0] > self.x and pos[0] < self.x + self.width: if pos[1] > self.y and pos[1] < self.y + self.height: return True return False 如下:

EmptyFieldListFilter

有关详细信息,请参阅 the docs。另请参阅the release notes

该代码可用 here,如果您需要对其进行自定义或向后移植。

答案 2 :(得分:2)

根据MaxCore的回答,我创建了可用于修改标题和参数名称的自定义类:

class NotNullFilter(admin.SimpleListFilter):
    title = _('Filter title not set')

    parameter_name = 'parameter name not set'

    def lookups(self, request, model_admin):

        return (
            ('not_null', _('Not empty only')),
            ('null', _('Empty only')),
        )

    def queryset(self, request, queryset):

        if self.value() == 'not_null':
            is_null_false = {
                self.parameter_name + "__isnull": False
            }
            exclude = {
                self.parameter_name: ""
            }
            return queryset.filter(**is_null_false).exclude(**exclude)

        if self.value() == 'null':
            is_null_true = {
                self.parameter_name + "__isnull": True
            }
            param_exact = {
                self.parameter_name + "__exact": ""
            }
            return queryset.filter(Q(**is_null_true) | Q(**param_exact))


class YoutubeNotNullFilter(NotNullFilter):
    title = "Youtube"
    parameter_name = "youtube_videoid"

答案 3 :(得分:1)

基于MaxCore的回答的更灵活的版本,可即时创建新的类

def by_null_filter(attr, name, null_label='is Null', non_null_label='not Null', bool_dt=False, bool_value=False):

    class ByNullFilter(admin.SimpleListFilter):
        """List display filter to show null/not null values"""
        parameter_name = attr
        title = name

        def lookups(self, request, model_admin):
            if bool_dt:
                label_null = 'not %s' % attr
                label_non_null = attr
            elif bool_value:
                label_null = 'no'
                label_non_null = 'yes'
            else:
                label_null = null_label
                label_non_null = non_null_label

            return (
                ('not_null', label_non_null),
                ('null', label_null)
            )

        def queryset(self, request, queryset):
            filter_string = attr + '__isnull'
            if self.value() == 'not_null':
                is_null_false = {
                    filter_string: False
                }
                return queryset.filter(**is_null_false)

            if self.value() == 'null':
                is_null_true = {
                    filter_string: True
                }
                return queryset.filter(**is_null_true)

    return ByNullFilter

用法 如果您已处理 DateTime字段并且要对其进行过滤-它是否具有值或为空

# with default filter labels (`not Null`, `is Null`)
list_filter = (by_null_filter('processed', 'Processed'), )
# Processed header with labels based on field name (`processed`, `not processed`)
list_filter = (by_null_filter('processed', 'Processed', bool_dt=True), )
# Paid header filter with labels based on bool(end_time) (`yes`, `no`)
list_filter = (by_null_filter('end_time', 'Paid', bool_value=True), )

答案 4 :(得分:0)

K.H。对可以轻松重用的基类的方法对我来说真的很有帮助。我无法使用这个书面示例,但通过一个小小的调整,它可以完美地实现(Python 2.7,Django 1.10)来实现这一目标。

from django.contrib import admin


class NotNullFilter(admin.SimpleListFilter):
    title = 'Filter title not set'
    parameter_name = 'parameter name not set'

    def lookups(self, request, model_admin):
        return (
            ('not_null', 'Not empty only'),
            ('null', 'Empty only'),
        )

    def queryset(self, request, queryset):
        filter_string = self.parameter_name + '__isnull'
        if self.value() == 'not_null':
            is_null_false = {
                filter_string: False
            }
            return queryset.filter(**is_null_false)

        if self.value() == 'null':
            is_null_true = {
                filter_string: True
            }
            return queryset.filter(**is_null_true)


class YoutubeNotNullFilter(NotNullFilter):
    title = "Youtube"
    parameter_name = "youtube_videoid"


class SomeVideoClass(admin.ModelAdmin):
    ...
    list_filter = [YouTubeNotNullFilter, ...]