如何使用django-filter为非必填字段显示empty_label?

时间:2013-08-06 21:47:21

标签: python django django-filters

我使用以下设置应用了django-filters的基本示例: models.py

class Shopper(models.Model):
    FirstName = models.CharField(max_length=30)     
    LastName = models.CharField(max_length=30)      
    Gender_CHOICES = (
        ('','---------'),
        ('Male','Male'),
        ('Female','Female'),
    )
    Gender = models.CharField(max_length=6, choices=Gender_CHOICES, default=None)
        School_CHOICES = (
        ('','---------'),
        (u'1', 'Primary school'),
        (u'2', 'High School'),
        (u'3', 'Apprenticeship'),
        (u'4', 'BsC'),
        (u'5', 'MsC'),
        (u'6', 'MBA'),
        (u'7', 'PhD'),
    )
    HighestSchool = models.CharField(max_length=40, blank = True, choices = School_CHOICES,default=None)

views.py:

def shopperlist(request):
    f = ShopperFilter(request.GET, queryset=Shopper.objects.all())
    return render(request,'mysapp/emailcampaign.html', {'filter': f})

urls.py:

   url(r'^emailcampaign/$', views.shopperlist, name='EmailCampaign'),

模板:

{% extends "basewlogout.html" %}

{% block content %}
{% csrf_token %}
    <form action="" method="get">
    {{ filter.form.as_p }}
    <input type="submit" name="Filter" value="Filter" />
    </form>

        {% for obj in filter %}
            <li>{{ obj.FirstName }} {{ obj.LastName }} {{ obj.Email }}</li>
        {% endfor %}

       <a href="{% url 'UserLogin' %}"> 
       <p> Return to home page. </p> </a>
{% endblock %}

forms.py:

class ShopperForm(ModelForm):

    class Meta:
        model = Shopper

添加了空选项('','---------')以确保django-filters在过滤期间显示它并且不指定该字段。但是,对于非强制性HighestSchool字段,在使用ModelForm. I.e的创建方案中使用模型时,它会显示两次。不应列出非强制性字段('','---------')。然后在过滤期间无法选择empty_label ...

如何通过在创建视图中列出一个empty_label来解决这个问题,并且可以在过滤期间保留未指定的强制字段和非强制字段?

2 个答案:

答案 0 :(得分:6)

首先,您不应将空白选项添加到您的选择集中。所以请删除以下内容:

('','---------'),

当不需要Field时,Django会自动添加这些内容(django模型,django形式,django视图等)除了 django-filter将按预期工作。

现在,关于django-filter。您所描述的是一个常见的要求,已经出现在django-filter project的问题中。请在此处查看可能的解决方法https://github.com/alex/django-filter/issues/45。我将从那里复制粘贴cvk77的代码以供参考:

class NicerFilterSet(django_filters.FilterSet):

def __init__(self, *args, **kwargs):
  super(NicerFilterSet, self).__init__(*args, **kwargs)

  for name, field in self.filters.iteritems():
    if isinstance(field, ChoiceFilter):
      # Add "Any" entry to choice fields.
      field.extra['choices'] = tuple([("", "Any"), ] + list(field.extra['choices']))`

所以使用它只是从NicerFilterSet而不是普通的FilterSet扩展你的过滤器。

您还可以执行以下Q + D解决方案:在models.py中定义全局变量:

GENDER_CHOICES = (
  ('Male','Male'),
  ('Female','Female'),
)

并在模型中按预期使用它。

现在,在您的filters.py中定义另一个全局变量:

FILTER_GENDER_CHOICES = list(models.FILTER_CHOICES)
FILTER_GENDER_CHOICES.insert(0, ('','---------') )

然后像这样定义你的过滤器:

class ShopperFilter(django_filters.FilterSet):
  gender = django_filters.ChoiceFilter(choices= FILTER_GENDER_CHOICES ) 
  class Meta:
    model = models.Shopper

答案 1 :(得分:0)

对于经验较少的人来说,这是cvk77原始解决方案的Python3兼容版本,我在@Serafeim接受的答案中找到了。

class NicerFilterSet(django_filters.FilterSet):

def __init__(self, *args, **kwargs):
  super(NicerFilterSet, self).__init__(*args, **kwargs)

  for name, field in self.filters.items():
    if isinstance(field, ChoiceFilter):
      # Add "Any" entry to choice fields.
      field.extra['choices'] = tuple([("", "Any"), ] + list(field.extra['choices']))

的变化:

  • self.filters.iteritems()已更改为self.filters.items()
  • 删除错误的反引号(它也存在于github线程中 - 没有@Serafeim的错误)