How to display a boolean property in the django admin

后端 未结 5 1366
说谎
说谎 2021-01-31 15:47

As we all know, displaying a method return value as boolean in the Django admin is easily done by setting the boolean attribute:

class MyMo         


        
相关标签:
5条回答
  • 2021-01-31 16:25

    You can create a decorator like this

    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
    

    here are your model and admin definitions:

    # 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)]
    

    for readonly fields in modeladmin you can use this decorator instead:

    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)
    
    0 讨论(0)
  • 2021-01-31 16:31

    You need to create a shadowing function to the property in the model. What I mean is that you will need to recreate a function in the ModelAdmin class with the same name as the property defined in the main Model.

    Example:

    # 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        
    
    0 讨论(0)
  • 2021-01-31 16:34

    this is the simplest way I found, directly in the 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']
    
    0 讨论(0)
  • 2021-01-31 16:37

    If you define is_something as a property, it will be an immutable object, instead of a function, but that object contains a reference to the decorated getter in the fget attribute. I think that the Django admin interface use the getter of that property, thus this may works

    class MyModel(models.Model):
        @property
        def is_something(self):
            if self.something == 'something':
                return True
            return False
        is_something.fget.boolean = True
    
    0 讨论(0)
  • 2021-01-31 16:43

    Waiting for better solutions to come up, I've solved it in the following way:

    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)
    

    I'll then reference the _is_something method in the ModelAdmin subclass:

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

    And the is_something property otherwise:

    if my_model_instance.is_something:
        print("I'm something")
    
    0 讨论(0)
提交回复
热议问题