How to override (filter based on particular condition) Django admin filter choices?

时间:2018-02-03 10:13:08

标签: django django-admin django-admin-filters

My models Django are:

class Brand(models.Model):
    name = models.CharField(max_length=200)

class StanardProduct(models.Model):
    brand = models.ForeignKey(Brand)

class VendorProduct(models.Model):
    standard_product = models.ForeignKey(StanardProduct)

My model admin is:

class StandardProductModelAdmin(admin.ModelAdmin):

    list_filter [
        'brand'
    ]

In the list filter for 'brand', I want to show only those brand choices that satisfy following two conditions:

  1. Brand name choice should be referenced by StandardProduct object
  2. StandardProduct object should be referenced by VendorProduct object

Using "admin.RelatedOnlyFieldListFilter" in the filter satisfies only condition no. 1 - but not no. 2. I need a way that satisfies both the conditions.

2 个答案:

答案 0 :(得分:2)

Sub-classing" admin.RelatedOnlyFieldListFilter"并且重写方法" field_choices"成功了!

class CustomRelatedOnlyFieldListFilter(admin.RelatedOnlyFieldListFilter):

    def field_choices(self, field, request, model_admin):
        custom_qs = model_admin.get_queryset(request).exclude(
            vendorproduct=None
        )
        pk_qs = custom_qs.distinct().values_list(
            'brand__pk', flat=True
        )
        return field.get_choices(include_blank=False, limit_choices_to={'pk__in': pk_qs})

管理员将是:

class StandardProductModelAdmin(admin.ModelAdmin):

    list_filter [
        ('brand', CustomRelatedOnlyFieldListFilter),
    ]

答案 1 :(得分:0)

您可以通过编写自定义列表过滤器(让我们说CustomStanardProductFilter)然后在list_filter中使用它来实现这一目标:

from django.contrib.admin import SimpleListFilter

class CustomStanardProductFilter(SimpleListFilter):
    def lookups(self, request, model_admin):
        ...

    def queryset(self, request, queryset):
        ...

class StandardProductModelAdmin(admin.ModelAdmin):
    list_filter [
        'CustomStanardProductFilter'
    ]

有关完整示例,请参阅this

希望它有所帮助。