如何在 django admin 中显示布尔属性

Posted

技术标签:

【中文标题】如何在 django admin 中显示布尔属性【英文标题】:How to display a boolean property in the django admin 【发布时间】:2012-10-02 06:24:52 【问题描述】:

众所周知,通过设置boolean 属性,可以很容易地在 Django 管理中将 方法 返回值显示为布尔值:

class MyModel(models.Model):
    def is_something(self):
        if self.something == 'something':
            return True
        return False
    is_something.boolean = True

你怎样才能为一个属性实现同样的效果,比如下面的例子?

class MyModel(models.Model):
    @property
    def is_something(self):
        if self.something == 'something':
            return True
        return False

【问题讨论】:

【参考方案1】:

这是我找到的最简单的方法,直接在 ModelAdmin 中:

class MyModelAdmin(admin.ModelAdmin):
    def is_something(self, instance):
        return instance.something == "something"
    is_something.boolean = True
    is_something.short_description = u"Is something"

    list_display = ['is_something']

【讨论】:

对我有用,但我需要将 list_display = ['is_something'] 更改为 list_display = ['_is_something'] 并将 @property 添加到我的模型函数中才能工作。 如果你之前用is_something()调用这个方法要小心,现在你需要在没有双亲的情况下调用它is_something 更好的解决方案,因为它不需要用管理相关的东西污染你的模型。【参考方案2】:

等待更好的解决方案出现,我通过以下方式解决了它:

class MyModel(models.Model):
    def _is_something(self):
        if self.something == 'something':
            return True
        return False
    _is_something.boolean = True
    is_something = property(_is_something)

然后我将在ModelAdmin 子类中引用_is_something 方法:

class MyModelAdmin(admin.ModelAdmin):
    list_display = ['_is_something']

否则is_something 属性:

if my_model_instance.is_something:
    print("I'm something")

【讨论】:

使用 django-jet 我遇到了这个问题,它与 CSS 不显示图标有关,具体取决于主题 github.com/geex-arts/django-jet/issues/300【参考方案3】:

您需要为模型中的属性创建一个shadowing 函数。我的意思是,您需要在 ModelAdmin 类中重新创建一个与主模型中定义的属性同名的函数。

例子:

# Model
class Product(models.Model):

    @property  # you can omit this decorator if you will access this property as a method of the model instance
    def in_stock(self):
        # boolean check return
        return self.quantity > 0

...

# Django-modeladmin
class ProductAdmin(admin.ModelAdmin):
    list_display = ('in_stock', ...)
    def in_stock(self, instance):
        return instance.in_stock

    in_stock.boolean = True        

【讨论】:

【参考方案4】:

你可以像这样创建一个装饰器

from six.moves import reduce

def list_property(field_name, **kwargs):
    def _from_property(obj):
        rv = reduce(getattr, field_name.split("."), obj)
        return rv() if callable(rv) else rv

    for key, value in kwargs.items():
        setattr(_from_property, key, value)
    return _from_property

这是您的模型和管理员定义:

# model

class MyModel(models.Model):
    @property
    def is_something(self):
        if self.something == 'something':
            return True
        return False


# admin

class MyModelAdmin(admin.ModelAdmin):
    list_display = [list_property("is_something", boolean=True)]

对于 modeladmin 中的只读字段,您可以改用这个装饰器:

def field_property(field_name, **kwargs):
    def _from_property(admin, obj=None):
        if not obj:
            return None
        rv = reduce(getattr, field_name.split("."), obj)
        return rv() if callable(rv) else rv

    for key, value in kwargs.items():
        setattr(_from_property, key, value)
    return _from_property

# admin
class MyModelAdmin(admin.ModelAdmin):
    readonly_fields = ["is_something"]

    is_something = field_property("is_something", boolean=True)

【讨论】:

对两种情况都有一个装饰器的小改进:def _from_property(admin_or_obj, obj=None): if not isinstance(admin_or_obj, admin.ModelAdmin): obj = admin_or_obj【参考方案5】:

如果您将is_something 定义为属性,它将是一个不可变对象,而不是一个函数,但该对象在fget 属性中包含对修饰getter 的引用。我认为 Django 管理界面使用该属性的 getter,因此这可能有效

class MyModel(models.Model):
    @property
    def is_something(self):
        if self.something == 'something':
            return True
        return False
    is_something.fget.boolean = True

【讨论】:

你在list_display里放了什么?如果你放 is_something.fget 它可能会起作用(但我认为这非常接近你的解决方案) 也不起作用,Django 明确禁止这样做。然后我会将我的解决方案标记为已接受,无论如何谢谢;)

以上是关于如何在 django admin 中显示布尔属性的主要内容,如果未能解决你的问题,请参考以下文章

django admin图片上传回显

stark组件之批量操作模仿Django的admin

在 Django Admin 中使用属性

如何在 Django Admin 中设置另一个内联标题?

django-19.admin后台自定义显示

Django Admin:如何过滤特定范围值的整数字段