我的
models.py
:
from smart_selects.db_fields import ChainedForeignKey
class Funder(models.Model):
name = models.CharField(max_length=200)
scheme = models.ManyToManyField('Scheme', blank=True)
class Scheme(models.Model):
name = models.CharField(max_length=200)
class Project(models.Model):
funder = models.ForeignKey(Funder, on_delete=models.PROTECT)
scheme = ChainedForeignKey(
Scheme,
chained_field="funder",
chained_model_field="funder",
show_all=False,
auto_choose=True,
sort=True, null=True, blank=True)
如您所见,我已经在使用 smart-selects 来仅获取属于管理后端的
Project
下拉选择中可用的特定资助者的计划。不过,smart-selects
并不关心管理员的 list_filters
部分中发生的情况。
我想要实现的目标:在我的项目管理表中有两个“链接”下拉过滤器,我在其中过滤具有特定资助者的项目,一旦我过滤了此类项目,我只想查看
scheme
下拉列表中属于该特定funder
的scheme
,能够进一步过滤具有该特定方案的项目。
到目前为止我的失败尝试(
admin/py
):
from admin_auto_filters.filters import AutocompleteFilter, AutocompleteFilterFactory
class SchemeFilter(
AutocompleteFilterFactory(
'new Scheme', 'scheme'
)
):
def lookups(self, request, model_admin):
funder = request.GET.get('funder__pk__exact', '')
if funder:
schemes= Scheme.objects.filter(funder__exact=funder).distinct()
else:
schemes = Scheme.objects.none()
return schemes
def queryset(self, request, queryset):
funder = request.GET.get('funder__pk__exact', '')
if funder and Scheme.objects.filter(funder__exact=funder).count():
return queryset.filter(scheme__exact=self.value())
return queryset
class FunderFilter(AutocompleteFilter):
title = 'Funder'
field_name = 'funder'
class ProjectAdmin(NumericFilterModelAdmin, ImportExportModelAdmin):
search_fields = ['title', 'project_number']
list_filter = [FunderFilter, SchemeFilter,]
[...]
您可以通过重写 ModelAdmin 类中的一些方法来做到这一点。
enter code here class ProjectAdmin(admin.ModelAdmin):
list_filter = ('funder', 'scheme')
def get_changelist_instance(self, request):
changelist_instance = super().get_changelist_instance(request)
funder_filter = changelist_instance.get_filters(request)[0][0]
funder_id = funder_filter.used_parameters.get('funder', None)
if funder_id:
self.list_filter = (
('funder', admin.RelatedOnlyFieldListFilter),
('scheme', admin.RelatedOnlyFieldListFilter),
)
else:
self.list_filter = ('funder',)
return changelist_instance
在此代码中,重写 ModelAdmin 的 get_changelist_instance 方法。调用父级的 get_changelist_instance 方法来获取 ChangeList 实例。然后获取资助者过滤器并检查它是否已被使用(即用户是否选择了资助者)。如果已选择资助者,我们将 list_filter 属性设置为包括资助者和方案过滤器。如果未选择资助者,我们仅包含资助者筛选器。
这样,方案过滤器仅在选择资助者后才会出现,并且仅包含与所选资助者相关的方案。