【问题标题】:django admin list filter queryset dependent on change list resultsdjango 管理列表过滤查询集依赖于更改列表结果
【发布时间】:2016-02-19 04:12:22
【问题描述】:

这适用于 Django 1.8

models.py

class ProductClass(models.Model):
    product_class = models.CharField(max_length=30)

    def __unicode__(self):
        return self.secondary_class  


class Product(models.Model):
    name= models.CharField(max_length=30)
    product_class = models.ForeignKey(ProductClass, db_index=True)

    def __unicode__(self):
        return self.name

我想在 ProductAdmin 中显示一个列表过滤器,其中包含一个列表,如果产品分类与每个条目旁边的产品数量。

按产品类别

  • 书籍 (100)
  • 钢笔 (10)
  • 统治者 (33)

我已经为超级数据集做到了这一点

admin.py

class DynamicProductClassFilter(admin.SimpleListFilter):
    title = _('Product Class')    

    # Parameter for the filter that will be used in the URL query.
    parameter_name = 'p_class'         

    def lookups(self, request, model_admin):
        classes = ProductClass.objects.annotate(number_products=Count('product'))

        return [(c.id, '%s (%s)' % (c.product_class , c.number_products)) for c in classes]

现在我想根据应用于数据集的其他过滤器更新此内容,无论是搜索条件还是其他正在应用的列表过滤器。

我认为我可以使用“请求”和“模型管理员”在列表过滤器的“定义查询集”中可用的事实。经过多次不同的尝试,我最终得到了以下代码

def lookups(self, request, model_admin):
    products = model_admin.get_queryset(request)
    product_ids = products.values_list('id', flat=True)
    classes = ProductClass.objects.filter(product__id__in=product_ids).annotate(number_products=Count('product'))

    return [(c.id, '%s (%s)' % (c.product_class, c.number_products)) for c in classes]

但不幸的是,这并没有将过滤器应用于主数据集。

我对 django 和 python 很陌生,所以如果这里缺少基本知识,我深表歉意。

【问题讨论】:

    标签: django django-admin django-filters


    【解决方案1】:

    我现在找到了一个适合我的解决方案,但我仍然希望得到反馈/建议,了解如何以更通用/可维护的方式更好地完成这项工作。

    def lookups(self, request, model_admin):
        concept_filter = request.GET.get('p_concept', None)
        if concept_filter:
            classes = ProductClass.objects.filter(product__title__concept_id=concept_filter).annotate(number_products=Count('product'))
        else:
            classes = ProductClass.objects.annotate(number_products=Count('product'))
    
        return [(c.id, '%s (%s)' % (c.product_class, c.number_products)) for c in classes]
    

    我发现我可以使用

    将过滤条件应用于更改列表数据集
    concept_filter = request.GET.get('p_concept', None)
    

    这对于我的用例来说工作得很好,因为我希望这个列表过滤器只依赖于另一个过滤器。

    知道如何修改这个解决方案会很有趣,这样您就可以遍历所有查询参数并知道如何正确构造查询。我不知道你会从哪里获得参数名称和它需要过滤的列之间的关联。也许只是命名约定在这里会有所帮助。

    【讨论】:

      猜你喜欢
      • 2020-05-23
      • 2019-08-08
      • 2021-11-14
      • 1970-01-01
      • 2014-03-31
      • 1970-01-01
      • 2011-01-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多