过滤Django管理员Null /不是空的 [英] Filtering Django Admin by Null/Is Not Null

查看:188
本文介绍了过滤Django管理员Null /不是空的的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a simple Django model like:

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

ModelAdmin,我如何允许通过引用者是否为null来过滤?默认情况下,将引荐来源添加到list_filter会导致显示一个下拉列表,其中列出了每个个人记录(可能在几十万个)中,有效地阻止了页面的加载。即使加载,我仍然不能按照我想要的标准进行过滤。

In this model's ModelAdmin, how would I allow it to be filtered by whether or not referrer is null? By default, adding referrer to list_filter causes a dropdown to be shown that lists every person record, which may be in the hundreds of thousands, effectively preventing the page from loading. Even if it loads, I still can't filter by the criteria I want.

我如何修改这个下拉列表仅列出全部,空或不空选项?

i.e. How would I modify this so that the dropdown only lists "All", "Null", or "Not Null" choices?

我看到一些 posts 声称使用自定义FilterSpec子类完成类似的操作,但都没有解释如何使用它们。我看过的几个似乎适用于所有型号的所有字段,我不想要的。此外,FilterSpec有一个文档,这让我很紧张,因为我不想投入大量与下一个版本可能会消失的短暂内部类的代码。 p>

I've seen some posts that claim to accomplish something similar using custom FilterSpec subclasses, but none of them explain how to use them. The few I've seen appear to apply to all fields in all models, which I wouldn't want. Moreover, there's zero documentation for FilterSpec, which makes me nervous, because I don't want to invest in a lot of custom code tied to some transient internal class that might disappear by the next release.

推荐答案

我结束了使用这里的顶级解决方案,以及此代码段

I ended up using a mixture of the top solution here, along with this snippet.

但是,我不得不稍微调整该片段,删除字段类型限制并添加新的field_path,最近在1.3中添加。

However, I had to tweak the snippet slightly, dropping the field type restriction and adding the new field_path, recently added in 1.3.

from django.contrib.admin.filterspecs import FilterSpec
from django.db import models
from django.utils.safestring import mark_safe
from django.utils.translation import ugettext as _

class NullFilterSpec(FilterSpec):
    #fields = (models.CharField, models.IntegerField, models.FileField)

    @classmethod
    def test(cls, field):
        #return field.null and isinstance(field, cls.fields) and not field._choices
        return field.null and not field._choices
    #test = classmethod(test)

    def __init__(self, f, request, params, model, model_admin, field_path=None):
        super(NullFilterSpec, self).__init__(f, request, params, model, model_admin, field_path)
        self.lookup_kwarg = '%s__isnull' % f.name
        self.lookup_val = request.GET.get(self.lookup_kwarg, None)

    def choices(self, cl):
        # bool(v) must be False for IS NOT NULL and True for IS NULL, but can only be a string
        for k, v in ((_('All'), None), (_('Has value'), ''), (_('Omitted'), '1')):
            yield {
                'selected' : self.lookup_val == v,
                'query_string' : cl.get_query_string({self.lookup_kwarg : v}),
                'display' : k
            }

# Here, we insert the new FilterSpec at the first position, to be sure
# it gets picked up before any other
FilterSpec.filter_specs.insert(0,
    # If the field has a `profilecountry_filter` attribute set to True
    # the this FilterSpec will be used
    (lambda f: getattr(f, 'isnull_filter', False), NullFilterSpec)
)

这篇关于过滤Django管理员Null /不是空的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆