如何在 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 中显示布尔属性的主要内容,如果未能解决你的问题,请参考以下文章