将类与django-filters相关联

时间:2018-07-02 06:42:51

标签: python django django-filter django-filters

Bonjour,我有一个关于Django过滤器的问题。我的问题是: 我在models.py中定义了两个类:

class Volcano(models.Model):
    vd_id = models.AutoField("ID, Volcano Identifier (Index)",
                         primary_key=True)
    [...]

class VolcanoInformation(models.Model):

    # Primary key
    vd_inf_id = models.AutoField("ID, volcano information identifier (index)",
                             primary_key=True)

    # Other attributes
    vd_inf_numcal = models.IntegerField("Number of calderas")
    [...]

    # Foreign key(s)
    vd_id = models.ForeignKey(Volcano, null=True, related_name='vd_inf_vd_id',
                          on_delete=models.CASCADE)

其中两个通过vd_id属性链接。

我想开发一种搜索工具,允许用户根据火山口的火山口数量(vd_inf_numcal)进行搜索。

我正在使用django-filters,现在这里是我的filter.py:

from .models import *
import django_filters

class VolcanoFilter(django_filters.FilterSet):

    vd_name = django_filters.ModelChoiceFilter(
                                      queryset=Volcano.objects.values_list('vd_name', flat=True),
                                 widget=forms.Select, label='Volcano name',
                                 to_field_name='vd_name',
                                 )

    vd_inf_numcal = django_filters.ModelChoiceFilter(
                                   queryset=VolcanoInformation.objects.values_list('vd_inf_numcal', flat=True),
                                 widget=forms.Select, label='Number of calderas',
                                 )


    class Meta:
        model = Volcano
        fields = ['vd_name', 'vd_inf_numcal']

我的views.py是:

def search(request):
    feature_list = Volcano.objects.all()
    feature_filter = VolcanoFilter(request.GET, queryset = feature_list)

    return render(request, 'app/search_list.html', {'filter' : feature_filter, 'feature_type': feature_type})

在我的应用程序中,出现了可能的破火山口数目的下拉列表,但搜索没有返回正常结果,因为VolcanoInformation.vd_inf_numcal,VolcanoInformation.vd_id和Volcano.vd_id之间没有关系。

甚至说“选择一个有效的选择。该选择不是可用的选择之一。”

我的问题是如何使用django_filters建立此链接? 我想我应该在该类中编写一些方法,但是我完全不知道该怎么做。

如果有人得到了答案,我将不胜感激!

2 个答案:

答案 0 :(得分:0)

通常,您需要回答两个问题:

  • 我们要查询哪个字段以及需要生成什么查询/查询表达式。
  • 我们应该使用哪种类型的值进行过滤。

这些答案实质上是.filter()通话的左手和右手。

在这种情况下,您将在Volcano-Volcano信息关系(vd_inf_vd_id)的反面进行过滤,而不是针对火山的破火山口数量(vd_inf_numcal)。此外,您需要exact匹配项。

对于这些值,您需要一组包含整数的选项。

AllValuesFilter将查看DB列并从列值中生成选择。但是,不利的一面是,这些选择将不包含任何缺少的值,这些值在呈现时看起来很奇怪。您可以改写该字段,也可以使用普通的ChoiceFilter自己生成值。

def num_calderas_choices():
    # Get the maximum number of calderas
    max_count = VolcanoInformation.objects.aggregate(result=Max('vd_inf_numcal'))['result']

    # Generate a list of two-tuples for the select dropdown, from 0 to max_count
    # e.g, [(0, 0), (1, 1), (2, 2), ...]
    return zip(range(max_count), range(max_count))

class VolcanoFilter(django_filters.FilterSet):
    name = ...
    num_calderas = django_filters.ChoiceFilter(
        # related field traversal (note the connecting '__')
        field_name='vd_inf_vd_id__vd_inf_numcal',
        label='Number of calderas',
        choices=num_calderas_choices
    )

class Meta:
    model = Volcano
    fields = ['name', 'num_calderas']

请注意,我还没有亲自测试以上代码,但是它应该足够接近以使您入门。

答案 1 :(得分:0)

非常感谢!那正是我想要的!我不了解.filter()的工作原理。

对于其他属性,我所做的就是生成选择,但是以不同的方式。例如,如果我只想显示可用位置的列表,我将使用:

# Location attribute
loc = VolcanoInformation.objects.values_list('vd_inf_loc', flat=True)
vd_inf_loc = django_filters.ChoiceFilter(
                              field_name='vd_inf_vd_id__vd_inf_loc',
                              label='Geographic location',
                              choices=zip(loc, loc),
                                        )