将"django-filter"与CHOICES字段一起使用 - 需要"Any"选项

ano*_*ard 10 django django-filter

我正在使用非常酷的django-filter(来自: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']
Run Code Online (Sandbox Code Playgroud)

当我显示过滤器表单时,' assigned_to'获取'任意'选项,以及列出可用用户.'status'但是,该字段仅限于实际"_CHOICES"中列出的选项.

如何根据_CHOICES在字段中添加"任意"选项?

ano*_*ard 8

正如简短而甜蜜的"用法"文档所述,

过滤器还会获取任何传递给django.forms.Field构造函数的任意关键字参数 .

在我进一步观察之前,这并没有多大意义.在./django-filter/docs/ref/目录中,filters.txt它描述了过滤器字段以及它们默认与之交互的模型字段.(我想我的语言就在这里,如果没有,请纠正我).

因此,我们可以看到它ChoiceFilter用于"有选择"的任何字段.

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

需要一个额外的必需参数:ChoiceField.choices 2元组的可迭代(例如,列表或元组),用作此字段的选项.

所以你可以传递一个列表,而不仅仅是原始的Tuple选择集.

所以这可能不是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
            })
Run Code Online (Sandbox Code Playgroud)

在上面,我定义了_CHOICES,我定义了这个新的(上面提到的),并确保将原始选项附加到最后:

CHOICES_FOR_PRIORITY_FILTER = [
    ('', 'Any'),
]
CHOICES_FOR_PRIORITY_FILTER.extend(list(TICKET_PRIORITY_CHOICES))
Run Code Online (Sandbox Code Playgroud)

我在这里使用list()因为原始Choices是在一个元组中设置的,所以我想把它变成一个列表.此外,如果您收到NoneType错误,请确保您没有尝试分配"返回值" .extend(),因为没有.我绊倒了这个,因为我忘了这是一个方法list,而不是一个返回新列表的函数.

如果您知道更简单,更干燥或"pythonic"的方式,请告诉我!


mpa*_*paf 8

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

因此,您可以简单地将FILTER_CHOICES扩展为TICKET_STATUS_CHOICES以及带有空字符串的"any"选项:

FILTER_CHOICES = (
    ('new', 'New'),
    ('accepted', 'Accepted'),
    ('assigned', 'Assigned'),
    ('reopened', 'Reopened'),
    ('closed', 'Closed'),
    ('', 'Any'),
)
Run Code Online (Sandbox Code Playgroud)

而您的TicketFilter将是:

class TicketFilter(django_filters.FilterSet):

   status = django_filters.ChoiceFilter(choices=FILTER_CHOICES)

   class Meta:
      model = Ticket
      fields = ['assigned_to']
Run Code Online (Sandbox Code Playgroud)


Pau*_*ans 6

更短的是使用空标签:

class TicketFilter(FilterSet):

    status = ChoiceFilter(choices=Ticket.CHOICES, empty_label=ugettext_lazy(u'Any'))

    class Meta:
        model = Ticket
        fields = ('status', )
Run Code Online (Sandbox Code Playgroud)