代码之家  ›  专栏  ›  技术社区  ›  anonymous coward

将“django过滤器”与选项字段一起使用-需要“任意”选项

  •  7
  • anonymous coward  · 技术社区  · 16 年前

    我正在使用非常酷的django过滤器(通过: http://github.com/alex/django-filter )

    当我在对象列表页面上显示过滤器窗体时,对于FK字段,我 获取包含“----”的下拉列表,该下拉列表将导致 “任意”型过滤器。但我有一些选择设置为一个字段 模型,我希望得到相同的“任意”类型选项。 下面是models.py中的一个相关示例部分:

    TICKET_STATUS_CHOICES = (
        ('new', 'New'),
        ('accepted', 'Accepted'),
        ('assigned', 'Assigned'),
        ('reopened', 'Reopened'),
        ('closed', 'Closed'),
    )
    
    class Ticket(models.Model):
        assigned_to = models.ForeignKey(User, null=True, blank=True)
        status = models.CharField(max_length=20,
    choices=TICKET_STATUS_CHOICES, default='new')
    
    import django_filters
    
    class TicketFilter(django_filters.FilterSet):
        class Meta:
            model = Ticket
            fields = ['assigned_to', 'status']
    

    当我显示筛选窗体时,' assigned_to' 获取一个“any”选项,如下所示 以及列出可用的用户。这个 'status' 然而,该字段是 仅限于实际“_选项”中列出的选项。

    如何根据_选项向字段添加“any”选项?

    6 回复  |  直到 16 年前
        1
  •  10
  •   mpaf    13 年前

    DRY'er将使用已经定义的ChoiceFilter的'choices'参数。

    因此,您可以简单地将筛选选项扩展为您的票证状态选项,再加上带有空字符串的“any”选项:

    FILTER_CHOICES = (
        ('new', 'New'),
        ('accepted', 'Accepted'),
        ('assigned', 'Assigned'),
        ('reopened', 'Reopened'),
        ('closed', 'Closed'),
        ('', 'Any'),
    )
    

    您的票务过滤器将是:

    class TicketFilter(django_filters.FilterSet):
    
       status = django_filters.ChoiceFilter(choices=FILTER_CHOICES)
    
       class Meta:
          model = Ticket
          fields = ['assigned_to']
    
        2
  •  8
  •   anonymous coward    16 年前

    筛选器还接受传递到 django.forms.Field 构造器。

    ./django-filter/docs/ref/ 目录,有 filters.txt

    所以,我们可以看到 ChoiceFilter 用于“具有选项”的任何字段。

    查阅Django文档,这里重要的是表单字段,以及它们如何与模型交互。(使用Django表单)。所以我们找到了ChoiceField( http://docs.djangoproject.com/en/dev/ref/forms/fields/#choicefield

    接受一个额外的必需参数: 选择场 用作此字段选项的2元组的iterable(例如,列表或元组)。

    因此,您可以向它传递一个列表,而不仅仅是原始的元组选择集。

    所以这可能不是pythonic或DRY,但下面是我如何更改所讨论的模型的:

    class TicketFilter(django_filters.FilterSet):
        class Meta:
            model = Ticket
            fields = ['assigned_to', 'priority', 'status']
    
        def __init__(self, *args, **kwargs):
            super(TicketFilter, self).__init__(*args, **kwargs)
            self.filters['priority'].extra.update(
                {
                    'choices': CHOICES_FOR_PRIORITY_FILTER
                })
    

    除此之外,在定义my_选项的地方,我定义了这个新选项(如上所述),并确保将原始选项附加到末尾:

    CHOICES_FOR_PRIORITY_FILTER = [
        ('', 'Any'),
    ]
    CHOICES_FOR_PRIORITY_FILTER.extend(list(TICKET_PRIORITY_CHOICES))
    

    .extend() ,因为没有。我被这个绊倒了,因为我忘了这是一个成功的方法 list ,而不是返回新列表的函数。

    如果你知道一个更简单,更干燥或“pythonic”的方法来做这件事,请让我知道!

        3
  •  6
  •   Paul Bormans    9 年前

    更简短的是使用空标签:

    class TicketFilter(FilterSet):
    
        status = ChoiceFilter(choices=Ticket.CHOICES, empty_label=ugettext_lazy(u'Any'))
    
        class Meta:
            model = Ticket
            fields = ('status', )
    
        4
  •  3
  •   Wim Feijen    11 年前

    import django_filters
    
    from .models import Experiment
    
    EMPTY_CHOICE = ('', '---------'), # Don't forget the trailing comma
    
    class ExperimentFilter(django_filters.FilterSet):
        class Meta:
            model = Experiment
            fields = ['method__year',]
    
        def __init__(self, *args, **kwargs):
            super(ExperimentFilter, self).__init__(*args, **kwargs)
            self.filters['method__year'].extra['choices'] = EMPTY_CHOICE + \
                self.filters['method__year'].extra['choices']
    
        5
  •  1
  •   Visgean Skeloru    11 年前

    我结合了上面所有的方法,因为我不喜欢指定所有需要更新的字段,结果是这样的:

    import django_filters
    
    from django.db import models
    from django_filters.filters import ChoiceFilter
    
    EMPTY_CHOICE = ('', '---------')
    
    class TicketFilter(django_filters.FilterSet):
        def __init__(self, *args, **kwargs):
            super(TicketFilter, self).__init__(*args, **kwargs)
            # add empty choice to all choice fields:
            choices = filter(
                lambda f: isinstance(self.filters[f], ChoiceFilter),
                self.filters)
    
            for field_name in choices:
                extended_choices = ((EMPTY_CHOICE,) +
                                    self.filters[field_name].extra['choices'])
                self.filters[field_name].extra['choices'] = extended_choices
    

    谁来做这个工作。

        6
  •  0
  •   slfan Narendra    7 年前

    你可以简单地使用 null_label null_value

        my_field = MultipleChoiceFilter(choices=MY_CHOICES, null_label='Any', null_value='')