Django Admin中的自定义过滤器

时间:2015-09-22 13:16:22

标签: django django-admin

我正在使用Django 1.7.4。我想在过滤器中仅显示在CarMake模型的外国领域中使用的国家。我尝试了两种变体,但它不起作用。如果我在list_filter中简单地放入'country',它会显示所有国家/地区。我做错了什么?

#model.py

from apps.location.models import Country

class CarMake(BaseModel):
       name = models.CharField(max_length=100)
       country = models.ForeignKey(Country, blank=True, null=True)

    def __str__(self):
        return self.name

admin.py

from . import models
class CarMakeAdmin(admin.ModelAdmin):
    model = models.CarMake
    list_display = ('name', 'country')
    list_filter = (
        #(CountryFilter), -> Variant I
        ('country', 'RelatedOnlyFieldListFilter'), #Variant II
    )

变体I

class CountryFilter(admin.SimpleListFilter):
    title = _('by country')
    parameter_name = 'country'

    def lookups(self, request, model_admin):
        countries = set([c.country for c in model_admin.model.objects.all()])
        return [(c.id, c.name) for c in countries]

    def queryset(self, request, queryset):
        if self.value():
            return queryset.filter(country__id__exact=self.value())
        else:
            return queryset

变体II

class RelatedOnlyFieldListFilter(admin.RelatedFieldListFilter):
    def __init__(self, field, request, params, model, model_admin, field_path):
        self.request = request
        self.model_admin = model_admin
        super(RelatedOnlyFieldListFilter, self).__init__(field, request, params, model, model_admin, field_path)

    def choices(self, cl):
        limit_choices_to = set(self.model_admin.queryset(self.request).values_list(self.field.name, flat=True))
        self.lookup_choices = [(pk_val, val) for pk_val, val in self.lookup_choices if pk_val in limit_choices_to]
        return super(RelatedOnlyFieldListFilter, self).choices(cl)

1 个答案:

答案 0 :(得分:5)

最后,我找到了解决问题的方法。

class CountryFilter(admin.SimpleListFilter):
    title = _('Country')
    parameter_name = 'country'

    def lookups(self, request, model_admin):
        countries = []
        qs = Country.objects.filter(id__in = model_admin.model.objects.all().values_list('country_id', flat = True).distinct())
        for c in qs:
            countries.append([c.id, c.name])
        return countries

    def queryset(self, request, queryset):
        if self.value():
            return queryset.filter(country__id__exact=self.value())
        else:
            return queryset