Search code examples
djangodjango-admindjango-admin-filters

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


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.


Solution

  • Sub-classing "admin.RelatedOnlyFieldListFilter" and overriding emthod "field_choices" worked!

    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})
    

    And the admin will be:

    class StandardProductModelAdmin(admin.ModelAdmin):
    
        list_filter [
            ('brand', CustomRelatedOnlyFieldListFilter),
        ]