【问题标题】:How to build chained filter in django admin dashboard如何在 django 管理仪表板中构建链式过滤器
【发布时间】:2020-01-15 21:05:10
【问题描述】:

我想要 django-admin 仪表板中的链式过滤器,请帮助我实现它。 我有 3 个模型:- 董事会、年级和章节。 最初,当仪表板加载时,只会出现板过滤器,在选择板过滤器后,所有过滤器都应该出现,在选择等级后,该等级的所有章节都应该出现。

我尝试过RelatedDropdownFilter,但这很正常, 它不会修改下拉过滤器的视图部分,它会显示所有结果。

我的模型:-

class LmsBoard(models.Model):
    name = models.CharField(max_length=240)



class LmsGrade(models.Model):
    name = models.CharField(max_length=240)
    board = models.ForeignKey(LmsBoard, models.DO_NOTHING)


 class LmsSubject(models.Model):
    name = models.CharField(max_length=240)
    grade = models.ForeignKey(LmsGrade, models.DO_NOTHING)
    board = models.ForeignKey(LmsBoard,models.DO_NOTHING)

class LmsChapter(models.Model):
    name = models.CharField(max_length=240,default='None')
    subject = models.ForeignKey(LmsSubject, models.DO_NOTHING)

我的 admin.py:-

@admin.register(MyModel)
class MyModel(admin.ModelAdmin):
    list_display = (
    'board', 'grade', 'chapter',)
    list_filter = (
        ('board',RelatedDropdownFilter),
        ('grade', RelatedDropdownFilter),
        ('chapter', RelatedDropdownFilter),

我希望过滤器应该一个一个出现,并且应该包含最后一个选定项目的过滤器列表。

【问题讨论】:

    标签: python django filter django-admin django-filter


    【解决方案1】:

    我明白了,我只是举个例子

    简化形式如下:

    class Website(models.Model):
      url = models.URLField(unique=True)
    
    class Page(models.Model):
      website = models.ForeignKey(
        'Website',
        on_delete=models.CASCADE,
        related_name='pages'
      )
      url = models.URLField(max_length=2083)
      title = models.CharField(max_length=255)
      content = models.TextField()
    

    我在 admin.py 中设置了一个管理面板,如下所示:

    from django.contrib.admin import ModelAdmin
    
    class WebsiteAdmin(AdminViews):
      actions = [scrape_website]
    
      list_display = ['url']
      search_fields = ['url']
    

    现在我要做的是在右侧边栏中添加一个过滤器。它将允许我通过抓取/未抓取状态过滤网站。我认为“已抓取”是指一个网站在数据库中至少有一个页面,“未抓取”是指没有任何页面保存在数据库中的网站。

    这就是我们需要为 Django 管理员创建自定义过滤器的地方。像 Django 的许多事情一样,它非常简单,跟着我的手:

    from django.contrib.admin import ModelAdmin, SimpleListFilter
    
    class ScrapeStatusFilter(SimpleListFilter):
      title = 'Scrape status' # a label for our filter
      parameter_name = 'pages' # you can put anything here
    
      def lookups(self, request, model_admin):
        # This is where you create filter options; we have two:
        return [
            ('scraped', 'Scraped'),
            ('not_scraped', 'Not scraped'),
        ] 
    
      def queryset(self, request, queryset):
        # This is where you process parameters selected by use via filter options:
        if self.value() == 'scraped':
            # Get websites that have at least one page.
      return queryset.distinct().filter(pages__isnull=False)
        if self.value():
            # Get websites that don't have any pages.
            return queryset.distinct().filter(pages__isnull=True)
    

    最后一步是将 ScrapeStatusFilter 添加到 WebsiteAdmin:

    class WebsiteAdmin(AdminViews):
      actions = [scrape_website]
    
      list_display = ['url']
      search_fields = ['url']
      list_filter = (ScrapeStatusFilter, )
    

    应该就是这样。您现在可以通过自定义过滤器过滤网站列表。

    【讨论】:

      【解决方案2】:

      您需要使用 LmsBoard 的内置过滤器并为 LmsGrade 和 LmsSubjects 定义自定义链表过滤器..:

      
      class LmsGradeFilter(admin.SimpleListFilter):
          title = 'LmsGrade '
          parameter_name = 'grades'
      
          def lookups(self, request, model_admin):
              if 'sections' in request.GET:
                  id = request.GET['board__id__exact']
                  grades= LmsGrade.objects.filter(board__id__exact=id)
                  return [(s.id, s.name) for s in grades]
              else:
                  return None # the filter will not appear if the parent is not selected yet
      
          def queryset(self, request, queryset):
              if self.value():
                  return queryset.filter(grade__id__exact=self.value())
              else:
                  return queryset
      
      
      

      然后您可以定义一个链接的主题过滤器来检查所选成绩等等。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-05-01
        • 2011-12-31
        • 1970-01-01
        • 2022-06-17
        • 1970-01-01
        • 2016-12-20
        • 1970-01-01
        • 2015-07-31
        相关资源
        最近更新 更多