【问题标题】:How to display a boolean property in the django admin如何在 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

【问题讨论】:

    标签: django


    【解决方案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")
    

    【讨论】:

    【解决方案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 明确禁止这样做。然后我会将我的解决方案标记为已接受,无论如何谢谢;)
      猜你喜欢
      • 2022-01-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-27
      • 1970-01-01
      • 2019-09-16
      • 1970-01-01
      相关资源
      最近更新 更多