class DynamicLookupMixin(object): ''' A mixin to add support to related attributes like 'book_author' in django ModelAdmin list_display field creating callables on the fly ''' def __getattr__(self, attr): if ('__' in attr and not attr.startswith('_') and not attr.endswith('_boolean') and not attr.endswith('_short_description')): def dyn_lookup(instance): # traverse all __ lookups return reduce(lambda parent, child: getattr(parent, child), attr.split('__'), instance) # get admin_order_field, boolean and short_description dyn_lookup.admin_order_field = attr dyn_lookup.boolean = getattr(self, '{}_boolean'.format(attr), False) dyn_lookup.short_description = getattr( self, '{}_short_description'.format(attr), attr.replace('_', ' ').capitalize()) return dyn_lookup # not dynamic lookup, default behaviour return self.__getattribute__(attr) # use examples @admin.register(models.Person) class PersonAdmin(admin.ModelAdmin, DynamicLookupMixin): list_display = ['book__author', 'book__publisher__name', 'book__publisher__country'] # custom short description book__publisher__country_short_description = 'Publisher Country' @admin.register(models.Product) class ProductAdmin(admin.ModelAdmin, DynamicLookupMixin): list_display = ('name', 'category__is_new') # to show as boolean field category__is_new_boolean = True