使用 list_filters 在 Django 后端条件性填充下拉列表

问题描述 投票:0回答:1

我的

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,]
[...]
python django django-filter
1个回答
0
投票

您可以通过重写 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 属性设置为包括资助者和方案过滤器。如果未选择资助者,我们仅包含资助者筛选器。

这样,方案过滤器仅在选择资助者后才会出现,并且仅包含与所选资助者相关的方案。

© www.soinside.com 2019 - 2024. All rights reserved.