def test_filtering(self): qs = mock.Mock(spec=['filter']) f = MultipleChoiceFilter(name='somefield') with mock.patch('django_filters.filters.Q') as mockQclass: mockQ1, mockQ2 = mock.MagicMock(), mock.MagicMock() mockQclass.side_effect = [mockQ1, mockQ2] f.filter(qs, ['value']) self.assertEqual(mockQclass.call_args_list, [mock.call(), mock.call(somefield='value')]) mockQ1.__ior__.assert_called_once_with(mockQ2) qs.filter.assert_called_once_with(mockQ1.__ior__.return_value) qs.filter.return_value.distinct.assert_called_once_with()
def test_null_multiplechoice(self): # default is to be disabled f = MultipleChoiceFilter(choices=[('a', 'a')], ) self.assertEqual(list(f.field.choices), [ ('a', 'a'), ]) # set label, allow blank label f = MultipleChoiceFilter(choices=[('a', 'a')], null_label='') self.assertEqual(list(f.field.choices), [ ('null', ''), ('a', 'a'), ]) # set null value f = MultipleChoiceFilter(choices=[('a', 'a')], null_value='NULL', null_label='') self.assertEqual(list(f.field.choices), [ ('NULL', ''), ('a', 'a'), ]) # explicitly disable f = MultipleChoiceFilter(choices=[('a', 'a')], null_label=None) self.assertEqual(list(f.field.choices), [ ('a', 'a'), ])
def test_filtering_skipped_when_len_of_value_is_len_of_field_choices(self): qs = mock.Mock(spec=[]) f = MultipleChoiceFilter(name='somefield') result = f.filter(qs, []) self.assertEqual(len(f.field.choices), 0) self.assertEqual(qs, result) f.field.choices = ['some', 'values', 'here'] result = f.filter(qs, ['some', 'values', 'here']) self.assertEqual(qs, result) result = f.filter(qs, ['other', 'values', 'there']) self.assertEqual(qs, result)
def test_filtering_skipped_when_len_of_value_is_len_of_field_choices(self): qs = mock.Mock(spec=[]) f = MultipleChoiceFilter(name='somefield') result = f.filter(qs, []) self.assertEqual(len(f.field.choices), 0) self.assertEqual(qs, result) f.field.choices = ['some', 'values', 'here'] result = f.filter(qs, ['some', 'values', 'here']) self.assertEqual(qs, result) result = f.filter(qs, ['other', 'values', 'there']) self.assertEqual(qs, result)
def test_filtering_exclude(self): qs = mock.Mock(spec=['exclude']) f = MultipleChoiceFilter(name='somefield', exclude=True) with mock.patch('django_filters.filters.Q') as mockQclass: mockQ1, mockQ2 = mock.MagicMock(), mock.MagicMock() mockQclass.side_effect = [mockQ1, mockQ2] f.filter(qs, ['value']) self.assertEqual(mockQclass.call_args_list, [mock.call(), mock.call(somefield='value')]) mockQ1.__ior__.assert_called_once_with(mockQ2) qs.exclude.assert_called_once_with(mockQ1.__ior__.return_value) qs.exclude.return_value.distinct.assert_called_once_with()
class MiscBooleanChoiceFiltersFilterSet(PropertyFilterSet): LOOKUP_CHOICES = [ (True, 'Yes'), # (True, 'True'), # (True, 'GiveMeYes'), (False, 'No'), # (False, 'False'), # (False, 'GiveMeNo'), ] is_true_ChoiceFilter = ChoiceFilter(field_name='is_true', lookup_expr='exact', choices=LOOKUP_CHOICES) is_true_MultipleChoiceFilter = MultipleChoiceFilter(field_name='is_true', lookup_expr='exact', conjoined=False, choices=LOOKUP_CHOICES) is_true_AllValuesFilter = AllValuesFilter(field_name='is_true', lookup_expr='exact') is_true_AllValuesMultipleFilter = AllValuesMultipleFilter( field_name='is_true', lookup_expr='exact', conjoined=False) # Typed Choice Filter might not have a blank option, skip #is_true_TypedChoiceFilter = TypedChoiceFilter(field_name='is_true', lookup_expr='exact', choices=LOOKUP_CHOICES, coerce=str) is_true_TypedMultipleChoiceFilter = TypedMultipleChoiceFilter( field_name='is_true', lookup_expr='exact', conjoined=False, choices=LOOKUP_CHOICES, coerce=str) prop_is_true_PropertyChoiceFilter = PropertyChoiceFilter( field_name='prop_is_true', lookup_expr='exact', choices=LOOKUP_CHOICES) prop_is_true_PropertyMultipleChoiceFilter = PropertyMultipleChoiceFilter( field_name='prop_is_true', lookup_expr='exact', conjoined=False, choices=LOOKUP_CHOICES) prop_is_true_PropertyAllValuesFilter = PropertyAllValuesFilter( field_name='prop_is_true', lookup_expr='exact') prop_is_true_PropertyAllValuesMultipleFilter = PropertyAllValuesMultipleFilter( field_name='prop_is_true', lookup_expr='exact', conjoined=False) # Typed Choice Filter might not have a blank option, skip #prop_is_true_PropertyTypedChoiceFilter = PropertyTypedChoiceFilter(field_name='prop_is_true', lookup_expr='exact', choices=LOOKUP_CHOICES, coerce=str) prop_is_true_PropertyTypedMultipleChoiceFilter = PropertyTypedMultipleChoiceFilter( field_name='prop_is_true', lookup_expr='exact', conjoined=False, choices=LOOKUP_CHOICES, coerce=str) class Meta: model = models.BooleanFilterModel exclude = ['is_true']
class ProfileFilter(django_filters.FilterSet): hair_colour = MultipleChoiceFilter( choices=Profile.HAIR_COLOUR, label="", widget=forms.SelectMultiple(attrs={'title': 'Hair Colour ▾'})) body_type = MultipleChoiceFilter( choices=Profile.BODY_TYPE, label="", widget=forms.SelectMultiple(attrs={'title': 'Body Type ▾'})) hair_length = MultipleChoiceFilter( choices=Profile.HAIR_LENGTH, label="", widget=forms.SelectMultiple(attrs={'title': 'Hair Lenght ▾'})) ethnicity = MultipleChoiceFilter( choices=Profile.ETHNICITY, label="", widget=forms.SelectMultiple(attrs={'title': 'Ethnicity ▾'})) relationship_status = MultipleChoiceFilter( choices=Profile.RELATIONSHIP_STATUS, label="", widget=forms.SelectMultiple(attrs={'title': 'Relationship Status ▾'})) gender = MultipleChoiceFilter( choices=Profile.GENDER, label="", widget=forms.SelectMultiple(attrs={'title': 'Gender ▾'})) class Meta: model = Profile # add age fields = [ 'hair_colour', 'body_type', 'hair_length', 'ethnicity', 'relationship_status', 'gender' ]
def test_settings_overrides(self): f = ChoiceFilter(choices=[('a', 'a')], ) self.assertEqual(list(f.field.choices), [ ('', 'EMPTY LABEL'), ('NULL VALUE', 'NULL LABEL'), ('a', 'a'), ]) f = MultipleChoiceFilter(choices=[('a', 'a')], ) self.assertEqual(list(f.field.choices), [ ('NULL VALUE', 'NULL LABEL'), ('a', 'a'), ])
class SiteFilterSet(ZoningFilterSet, StructureRelatedFilterSet): orientation = MultipleChoiceFilter(choices=Site.ORIENTATION_CHOICES, method='filter_super') wind = MultipleChoiceFilter(choices=Site.ORIENTATION_CHOICES, method='filter_super') practice = ModelMultipleChoiceFilter(queryset=Practice.objects.all(), method='filter_super') sector = ModelMultipleChoiceFilter(queryset=Sector.objects.all(), method='filter_sector', label=_("Sector")) class Meta(StructureRelatedFilterSet.Meta): model = Site fields = StructureRelatedFilterSet.Meta.fields + [ 'sector', 'practice', 'labels', 'themes', 'portal', 'source', 'information_desks', 'web_links', 'type', 'orientation', 'wind', ] def filter_super(self, qs, name, values): if not values: return qs return qs.filter(**{ '{}__in'.format(name): values }).get_ancestors(include_self=True) def filter_sector(self, qs, name, values): if not values: return qs return qs.filter(practice__sector__in=values).get_ancestors( include_self=True)
class EventSearchFilter(django_filters.FilterSet): ownership = MultipleChoiceFilter(choices=[('admin','Created'), ('joined',' Joined')], widget=forms.CheckboxSelectMultiple ) location = ChoiceFilter(name='location',choices=[('Venue','Venue'), ('Online','Online')], widget=forms.Select(attrs={'class': 'selects'})) city = CharFilter(name="city", lookup_expr="icontains", widget=forms.TextInput(attrs={'placeholder': 'City'})) state = CharFilter(name="state", lookup_expr="icontains", widget=forms.TextInput(attrs={'placeholder': 'State'})) country = CharFilter(name="india", lookup_expr="icontains", widget=forms.TextInput(attrs={'placeholder': 'India'})) category = ChoiceFilter(name="category",choices=[('Adventure','Adventure'), ('Business & Tech','Business & Tech'), ('Entertainment','Entertainment'), ('Social','Social'), ('Sports','Sports'), ('Talks','Talks')], widget=forms.Select(attrs={'class': 'selects'})) gender = ChoiceFilter(name='gender',choices=[('Male','Male'), ('Female','Female'), ('Others','Others'), ('Any', 'Any')], widget=forms.Select(attrs={'class': 'selects'})) age_group = ChoiceFilter(name='age',choices=[('Under 18','Under 18'), ('18-30','18-30'), ('30-50','30-50'), ('Above 50','Above 50')], widget=forms.Select(), lookup_expr="icontains", label='Age Group') year = NumberFilter(label='Start Date', name='start_date',lookup_expr='year', widget=forms.NumberInput(attrs={'class': 'form_inps', 'placeholder': 'Year'}) ) month = NumberFilter(label='Start Date', name='start_date',lookup_expr='month', widget=forms.NumberInput(attrs={'class': 'form_inps', 'placeholder': 'Month'}) ) day = NumberFilter(label='Start Date', name='start_date',lookup_expr='day', widget=forms.NumberInput(attrs={'class': 'form_inps', 'placeholder': 'Day'}) ) class Meta: model = Event fields = ['ownership']
class PropertyMultipleChoiceFilterSet(PropertyFilterSet): number_contains_and = MultipleChoiceFilter(field_name='number', lookup_expr='contains', label='Number Contains <AND>', conjoined=True, choices=[]) prop_number_contains_and = PropertyMultipleChoiceFilter( field_name='prop_number', lookup_expr='contains', label='Prop Number Contains <AND>', conjoined=True, choices=[]) class Meta: model = models.MultipleChoiceFilterModel exclude = ['number'] def __init__(self, *args, **kwargs): choices = [ (num, F'Number: {num}') for num in models.MultipleChoiceFilterModel.objects.values_list( 'number', flat=True).distinct() ] choices.append((-5, 'Number: -5')) choices.append((666, 'Number: 666')) self.base_filters['number_contains_and'].extra['choices'] = choices self.base_filters['prop_number_contains_and'].extra[ 'choices'] = choices add_supported_filters(self, MultipleChoiceFilter, 'number', PropertyMultipleChoiceFilter.supported_lookups, choices=choices) add_supported_property_filters( self, PropertyMultipleChoiceFilter, 'prop_number', PropertyMultipleChoiceFilter.supported_lookups, choices=choices) super().__init__(*args, **kwargs)
class TripSearchFilter(django_filters.FilterSet): dayslist = [(str(i),'0'+str(i)) for i in [i for i in range(1,10)]] + [(str(i),str(i)) for i in [i for i in range(10,32)]] monthslist = [(1,'Jan'), (2,'Feb'), (3,'Mar'), (4,'Apr'), (5,'May'), (6,'Jun'), (7,'Jul'), (8,'Aug'), (9,'Sep'), (10,'Oct'), (11,'Nov'), (12,'Dec')] yearslist = [(i, i) for i in range(2018,2050)] source = django_filters.CharFilter(label="Source:", lookup_expr='icontains', widget=forms.TextInput(attrs={})) destination = django_filters.CharFilter(label="Destination:", lookup_expr='icontains') company = ChoiceFilter(choices=[('Group','Group'), ('Solo','Solo')], widget=forms.Select() ) moto = ChoiceFilter(label='Travel Moto',choices=[('','Any'), ('Adventure','Adventure'), ('Exploring','Exploring'), ('Photography','Photography'), ('Sports Event','Sports Event'), ('Food & Cuisine','Food & Cuisine'), ('Fitness','Fitness'), ('Shopping','Shopping'), ('Travel Blogging','Travel Blogging'), ('Partying','Partying'), ('Backtracking','Backtracking')], widget=forms.Select() ) mode = ChoiceFilter(choices=[('Car','Car'), ('Motorbike','Motorbike'), ('Cycle','Cycle'), ('On-Foot','On-Foot'), ('Any', 'Any') ], widget=forms.Select() ) year = NumberFilter(label='Start Date', name='start_date',lookup_expr='year', widget=forms.NumberInput(attrs={'class': 'search_inputs', 'placeholder': 'Year'}) ) month = NumberFilter(label='Start Date', name='start_date',lookup_expr='month', widget=forms.NumberInput(attrs={'class': 'search_inputs', 'placeholder': 'Month'}) ) day = NumberFilter(label='Start Date', name='start_date',lookup_expr='day', widget=forms.NumberInput(attrs={'class': 'search_inputs', 'placeholder': 'Day'}) ) age_group = ChoiceFilter(choices=[('Under 18','Under 18'), ('18-30','18-30'), ('30-50','30-50'), ('Above 50','Above 50')], widget=forms.Select(), lookup_expr="icontains", label='Age Group' ) #year = ChoiceFilter(name='start_date',choices=yearslist, widget=forms.Select(attrs={'class': 'search_inputs'}) ) #start_date = django_filters.NumberFilter(name='start_date', lookup_expr='year') ownership = MultipleChoiceFilter(choices=[('admin','Created'), ('joined',' Joined')], widget=forms.CheckboxSelectMultiple ) location = ChoiceFilter(choices=[('male','Male'), ('female','Female'), ('others','Others'), ('any','Any')], widget=forms.Select()) gender = ChoiceFilter(choices=[('male','Male'), ('female','Female'), ('others','Others'), ('Any', 'Any')], widget=forms.Select(attrs={'class': 'selects'})) trip_id = django_filters.CharFilter(label="Trip id:", name="trip_id", lookup_expr='icontains', widget=forms.TextInput(attrs={})) class Meta: model = Trip fields = []
def test_filtering_requires_name(self): qs = mock.Mock(spec=['filter']) f = MultipleChoiceFilter() with self.assertRaises(TypeError): f.filter(qs, ['value'])
def test_filtering_requires_name(self): qs = mock.Mock(spec=['filter']) f = MultipleChoiceFilter() with self.assertRaises(TypeError): f.filter(qs, ['value'])
class ContatoAgrupadoPorProcessoFilterSet(FilterSet): AGRUPADO_POR_NADA = 'sem_agrupamento' AGRUPADO_POR_TITULO = 'titulo' AGRUPADO_POR_IMPORTANCIA = 'importancia' AGRUPADO_POR_TOPICO = 'topicos__descricao' AGRUPADO_POR_ASSUNTO = 'assuntos__descricao' AGRUPADO_POR_STATUS = 'status__descricao' AGRUPADO_POR_CLASSIFICACAO = 'classificacoes__descricao' AGRUPAMENTO_CHOICE = ( (AGRUPADO_POR_NADA, _('Sem Agrupamento')), (AGRUPADO_POR_TITULO, _('Por Título de Processos')), (AGRUPADO_POR_IMPORTANCIA, _('Por Importância')), (AGRUPADO_POR_TOPICO, _('Por Tópicos')), (AGRUPADO_POR_ASSUNTO, _('Por Assuntos')), (AGRUPADO_POR_STATUS, _('Por Status')), (AGRUPADO_POR_CLASSIFICACAO, _('Por Classificação')), ) search = CharFilter(method='filter_search') agrupamento = ChoiceFilter(required=False, empty_label=None, choices=AGRUPAMENTO_CHOICE, method='filter_agrupamento') importancia = MultipleChoiceFilter(required=False, choices=IMPORTANCIA_CHOICE, method='filter_importancia') status = ModelMultipleChoiceFilter(required=False, queryset=StatusProcesso.objects.all(), method='filter_status') def filter_agrupamento(self, queryset, field_name, value): return queryset def filter_importancia(self, queryset, field_name, value): if not value: return queryset q = None for i in value: q = q | Q(importancia=i) if q else Q(importancia=i) return queryset.filter(q) def filter_status(self, queryset, field_name, value): if not value: return queryset q = None for sta in value: q = q | Q(status=sta) if q else Q(status=sta) return queryset.filter(q) def filter_search(self, queryset, field_name, value): query = normalize(value) query = query.split(' ') if query: q = Q() for item in query: if not item: continue q = q & Q(search__icontains=item) if q: queryset = queryset.filter(q) return queryset class Meta: model = Processo fields = [ 'search', 'data', 'topicos', 'importancia', 'classificacoes', 'assuntos', 'status', ] filter_overrides = { models.DateField: { 'filter_class': DataRangeFilter, 'extra': lambda f: { 'label': '%s (%s)' % (f.verbose_name, _('Inicial - Final')), 'widget': RangeWidgetOverride } } } def __init__(self, data=None, queryset=None, prefix=None, **kwargs): workspace = kwargs.pop('workspace') super(ContatoAgrupadoPorProcessoFilterSet, self).__init__(data=data, queryset=queryset, prefix=prefix, **kwargs) c1_row1 = to_row([ ('search', 7), ('data', 5), ('importancia', 4), ('status', 4), ('classificacoes', 4), ('topicos', 6), ('assuntos', 6), ]) col1 = Fieldset( _('Informações para Seleção de Processos'), c1_row1, to_row([ (SubmitFilterPrint('filter', value=_('Filtrar'), css_class='btn-outline-primary pull-right', type='submit'), 12) ])) col2 = Fieldset( _('Inf p/ Impressão'), 'agrupamento', SubmitFilterPrint('print', value=_('Imprimir'), css_class='btn-primary pull-right', type='submit')) rows = to_row([ (col1, 9), (col2, 3), ]) self.form.helper = FormHelper() self.form.helper.form_method = 'GET' self.form.helper.layout = Layout(rows, ) self.form.fields['search'].label = _('Filtrar Títulos de Processos') self.form.fields['topicos'].widget = forms.SelectMultiple( attrs={'size': '7'}) self.form.fields['topicos'].queryset = TopicoProcesso.objects.all() self.form.fields['assuntos'].widget = forms.SelectMultiple( attrs={'size': '7'}) self.form.fields['assuntos'].queryset = AssuntoProcesso.objects.filter( workspace=workspace) self.form.fields['importancia'].widget = forms.CheckboxSelectMultiple() #self.form.fields['importancia'].inline_class = True self.form.fields[ 'classificacoes'].widget = forms.CheckboxSelectMultiple() self.form.fields['status'].widget = forms.CheckboxSelectMultiple() """#self.form.fields['status'].inline_class = True self.form.fields['status'].choices = list( self.form.fields['status'].choices) del self.form.fields['status'].choices[0]""" self.form.fields['agrupamento'].label = _('Agrupar Contatos') self.form.fields['agrupamento'].widget = forms.RadioSelect()
class F(FilterSet): lovers__username = MultipleChoiceFilter() class Meta: model = Book fields = ['lovers__username']
class F(FilterSet): favorite_books__title = MultipleChoiceFilter() class Meta: model = User fields = ['favorite_books__title']
class F(FilterSet): status = MultipleChoiceFilter(choices=STATUS_CHOICES) class Meta: model = User fields = ['status']
def test_filter_conjoined_true(self): """Tests that a filter with `conjoined=True` returns objects that have all the values included in `value`. For example filter users that have all of this books. """ book_kwargs = {'price': 1, 'average_rating': 1} books = [] books.append(Book.objects.create(**book_kwargs)) books.append(Book.objects.create(**book_kwargs)) books.append(Book.objects.create(**book_kwargs)) books.append(Book.objects.create(**book_kwargs)) books.append(Book.objects.create(**book_kwargs)) books.append(Book.objects.create(**book_kwargs)) user1 = User.objects.create() user2 = User.objects.create() user3 = User.objects.create() user4 = User.objects.create() user5 = User.objects.create() user1.favorite_books.add(books[0], books[1]) user2.favorite_books.add(books[0], books[1], books[2]) user3.favorite_books.add(books[1], books[2]) user4.favorite_books.add(books[2], books[3]) user5.favorite_books.add(books[4], books[5]) filter_list = ( ((books[0].pk, books[0].pk), # values [1, 2]), # list of user.pk that have `value` books ((books[1].pk, books[1].pk), [1, 2, 3]), ((books[2].pk, books[2].pk), [2, 3, 4]), ((books[3].pk, books[3].pk), [4, ]), ((books[4].pk, books[4].pk), [5, ]), ((books[0].pk, books[1].pk), [1, 2]), ((books[0].pk, books[2].pk), [2, ]), ((books[1].pk, books[2].pk), [2, 3]), ((books[2].pk, books[3].pk), [4, ]), ((books[4].pk, books[5].pk), [5, ]), ((books[3].pk, books[4].pk), []), ) users = User.objects.all() for item in filter_list: f = MultipleChoiceFilter(field_name='favorite_books__pk', conjoined=True) queryset = f.filter(users, item[0]) expected_pks = [c[0] for c in queryset.values_list('pk')] self.assertListEqual( expected_pks, item[1], 'Lists Differ: {0} != {1} for case {2}'.format( expected_pks, item[1], item[0]))
def test_filter_conjoined_true(self): """Tests that a filter with `conjoined=True` returns objects that have all the values included in `value`. For example filter users that have all of this books. """ book_kwargs = {'price': 1, 'average_rating': 1} books = [] books.append(Book.objects.create(**book_kwargs)) books.append(Book.objects.create(**book_kwargs)) books.append(Book.objects.create(**book_kwargs)) books.append(Book.objects.create(**book_kwargs)) books.append(Book.objects.create(**book_kwargs)) books.append(Book.objects.create(**book_kwargs)) user1 = User.objects.create() user2 = User.objects.create() user3 = User.objects.create() user4 = User.objects.create() user5 = User.objects.create() user1.favorite_books.add(books[0], books[1]) user2.favorite_books.add(books[0], books[1], books[2]) user3.favorite_books.add(books[1], books[2]) user4.favorite_books.add(books[2], books[3]) user5.favorite_books.add(books[4], books[5]) filter_list = ( ((books[0].pk, books[0].pk), # values [1, 2]), # list of user.pk that have `value` books ((books[1].pk, books[1].pk), [1, 2, 3]), ((books[2].pk, books[2].pk), [2, 3, 4]), ((books[3].pk, books[3].pk), [4, ]), ((books[4].pk, books[4].pk), [5, ]), ((books[0].pk, books[1].pk), [1, 2]), ((books[0].pk, books[2].pk), [2, ]), ((books[1].pk, books[2].pk), [2, 3]), ((books[2].pk, books[3].pk), [4, ]), ((books[4].pk, books[5].pk), [5, ]), ((books[3].pk, books[4].pk), []), ) users = User.objects.all() for item in filter_list: f = MultipleChoiceFilter(name='favorite_books__pk', conjoined=True) queryset = f.filter(users, item[0]) expected_pks = [c[0] for c in queryset.values_list('pk')] self.assertListEqual( expected_pks, item[1], 'Lists Differ: {0} != {1} for case {2}'.format( expected_pks, item[1], item[0]))
def test_filtering_skipped_with_empty_list_value_and_some_choices(self): qs = mock.Mock(spec=[]) f = MultipleChoiceFilter(name='somefield') f.field.choices = ['some', 'values', 'here'] result = f.filter(qs, []) self.assertEqual(qs, result)
def test_conjoined_true(self): f = MultipleChoiceFilter(conjoined=True) self.assertTrue(f.conjoined)
class CommunityFilter(django_filters.FilterSet): """Filter for Community.""" admin_areas = ModelMultipleChoiceFilter( label="DBCA Regions and Districts", queryset=Area.objects.filter(area_type__in=[ Area.AREATYPE_DBCA_REGION, Area.AREATYPE_DBCA_DISTRICT ]).order_by("area_type", "name"), method='communities_occurring_in_area') eoo = geo_models.PolygonField() aoo = CharFilter( label="Area of Occupancy (AOO) intersects", widget=LeafletWidget(), method="communities_occurring_in_poly", ) conservation_level = MultipleChoiceFilter( label="Conservation Level", choices=cons_models.ConservationCategory.LEVEL_CHOICES, method='community_conservation_level') categories = ModelMultipleChoiceFilter( label="Conservation Listing Categories", queryset=cons_models.ConservationCategory.objects.filter( conservation_list__scope_communities=True).order_by( "conservation_list__code", "rank").prefetch_related("conservation_list"), method="communities_with_conservation_criteria") class Meta: """Class opts.""" model = Community fields = [ "admin_areas", "eoo", "aoo", "conservation_level", "categories", "code", "name", "description", ] filter_overrides = FILTER_OVERRIDES def communities_occurring_in_area(self, queryset, name, value): """Return Communities occurring in the given Area. * The filter returns a list of Area objects as ``value`` * We need to extract their PKs to create a queryset equivalent to the list of objects ``value``. Only querysets allow agggregation, not lists. * A search_area Multipolygon is collected from the geoms of Areas in ``value`` * The Taxon PKs are calculated from occurrences (CommunityAreaEncounters) ``intersect``ing the search_area * The queryset is filtered by the list of Community PKs with occurrences in the matching areas """ if value: area_pks = [area.pk for area in value] search_area = Area.objects.filter(pk__in=area_pks).aggregate( Collect('geom'))["geom__collect"] pks = set([ x["community__pk"] for x in occ_models.CommunityAreaEncounter.objects.filter( Q(point__intersects=search_area) | Q(geom__intersects=search_area)).values("community__pk") ]) return queryset.filter(pk__in=pks) else: return queryset def communities_occurring_in_poly(self, queryset, name, value): """Return Communities occurring in the given Area polygon. * The filter returns a ``value`` * (magic) value becomes search area * The Community PKs are calculated from occurrences (CommunityAreaEncounters) ``intersect``ing the search_area * The queryset is filtered by the list of Community PKs with occurrences """ if value: pks = set([ x["community__pk"] for x in occ_models.CommunityAreaEncounter.objects.filter( Q(point__intersects=value) | Q(geom__intersects=value)).values("community__pk") ]) return queryset.filter(pk__in=pks) else: return queryset def community_conservation_level(self, queryset, name, value): """Return Communities matching a conservation level. * The filter returns a list of ConservationCategory levels as ``value`` * The Community PKs are calculated from active, WA CommunityConservationListings with categories matching the level * The queryset is filtered by the list of Community PKs with active community listings in WA matching the conservation level """ if value: pks = set([ x["community__pk"] for x in cons_models.CommunityConservationListing.objects. filter(scope=cons_models.ConservationListing. SCOPE_WESTERN_AUSTRALIA, status=cons_models.ConservationListing.STATUS_EFFECTIVE, category__level__in=value).values("community__pk") ]) return queryset.filter(pk__in=pks) else: return queryset def communities_with_conservation_criteria(self, queryset, name, value): """Return Communities matching a conservation level. * The filter returns a list of ConservationCategories as ``value`` * The Taxon PKs are calculated from CommunityConservationListings with categories matching the list of categories in ``value`` * The queryset is filtered by the list of Taxon PKs matching the conservation level """ if value: pks = set([ x["community__pk"] for x in cons_models.CommunityConservationListing.objects. filter(category__in=value).values("community__pk") ]) return queryset.filter(pk__in=pks) else: return queryset
class TaxonFilter(django_filters.FilterSet): """Filter for Taxon.""" is_terminal_taxon = BooleanFilter(label="Terminal Taxon", widget=BooleanWidget(), method="filter_leaf_nodes") current = BooleanFilter(label="Taxonomic name is current", widget=BooleanWidget()) admin_areas = ModelMultipleChoiceFilter( label="DBCA Regions and Districts", queryset=Area.objects.filter(area_type__in=[ Area.AREATYPE_DBCA_REGION, Area.AREATYPE_DBCA_DISTRICT ]).order_by("area_type", "name"), method='taxa_occurring_in_area') eoo = geo_models.PolygonField() aoo = CharFilter( label="Area of Occupancy (AOO) intersects", widget=LeafletWidget(), method="taxa_occurring_in_poly", ) conservation_level = MultipleChoiceFilter( label="Conservation Level", choices=cons_models.ConservationCategory.LEVEL_CHOICES, method='taxon_conservation_level') categories = ModelMultipleChoiceFilter( label="Conservation Listing Categories", queryset=cons_models.ConservationCategory.objects.filter( conservation_list__scope_species=True).order_by( "conservation_list__code", "rank").prefetch_related("conservation_list"), method="taxa_with_conservation_criteria") class Meta: """Class opts.""" model = Taxon fields = [ "paraphyletic_groups", "admin_areas", "eoo", "aoo", "conservation_level", "categories", "taxonomic_name", "vernacular_names", "rank", "is_terminal_taxon", "current", "publication_status", "name_id", "field_code" ] filter_overrides = FILTER_OVERRIDES def filter_leaf_nodes(self, queryset, name, value): """Return terminal taxa (leaf nodes) if value is true.""" return queryset.filter(children__isnull=value) def taxa_occurring_in_area(self, queryset, name, value): """Return Taxa occurring in the given list of ``Area`` instances. * The filter returns a list of Area objects as ``value`` * We need to extract their PKs to create a queryset equivalent to the list of objects ``value``. Only querysets allow agggregation, not lists. * A search_area Multipolygon is collected from the geoms of Areas in ``value`` * The Taxon PKs are calculated from occurrences (TaxonAreaEncounters) ``intersect``ing the search_area * The queryset is filtered by the list of Taxon PKs with occurrences """ if value: area_pks = [area.pk for area in value] search_area = Area.objects.filter(pk__in=area_pks).aggregate( Collect('geom'))["geom__collect"] taxon_pks_in_area = set([ x["taxon__pk"] for x in occ_models.TaxonAreaEncounter.objects.filter( Q(point__intersects=search_area) | Q(geom__intersects=search_area)).values("taxon__pk") ]) return queryset.filter(pk__in=taxon_pks_in_area) else: return queryset def taxa_occurring_in_poly(self, queryset, name, value): """Return Taxa occurring in the given Area polygon. * The filter returns a ``value`` * (magic) value becomes search area * The Taxon PKs are calculated from occurrences (TaxonAreaEncounters) ``intersect``ing the search_area * The queryset is filtered by the list of Taxon PKs with occurrences """ if value: taxon_pks_in_area = set([ x["taxon__pk"] for x in occ_models.TaxonAreaEncounter.objects.filter( Q(point__intersects=value) | Q(geom__intersects=value)).values("taxon__pk") ]) return queryset.filter(pk__in=taxon_pks_in_area) else: return queryset def taxon_conservation_level(self, queryset, name, value): """Return Taxa matching a conservation level. * The filter returns a list of ConservationCategory levels as ``value`` * The Taxon PKs are calculated from active, WA CommunityConservationListings with categories matching the level * The queryset is filtered by the list of Taxon PKs with active taxon listings in WA matching the conservation level """ if value: taxon_pks = set([ x["taxon__pk"] for x in cons_models.TaxonConservationListing.objects.filter( scope=cons_models.ConservationListing. SCOPE_WESTERN_AUSTRALIA, status=cons_models.ConservationListing.STATUS_EFFECTIVE, category__level__in=value).values("taxon__pk") ]) return queryset.filter(pk__in=taxon_pks) else: return queryset def taxa_with_conservation_criteria(self, queryset, name, value): """Return Taxa matching a conservation level. * The filter returns a list of ConservationCategories as ``value`` * The Taxon PKs are calculated from TaxonConservationListings with categories matching the list of categories in ``value`` * The queryset is filtered by the list of Taxon PKs matching the conservation level """ if value: taxon_pks = set([ x["taxon__pk"] for x in cons_models.TaxonConservationListing.objects.filter( category__in=value).values("taxon__pk") ]) return queryset.filter(pk__in=taxon_pks) else: return queryset
def test_default_field(self): f = MultipleChoiceFilter() field = f.field self.assertIsInstance(field, forms.MultipleChoiceField)
class F(FilterSet): class Meta: model = Article fields = ['id', 'author', 'name'] choice = MultipleChoiceFilter(choices=[('1', 'one'), ('2', 'two')])
def test_filtering_skipped_with_empty_list_value_and_some_choices(self): qs = mock.Mock(spec=[]) f = MultipleChoiceFilter(name='somefield') f.field.choices = ['some', 'values', 'here'] result = f.filter(qs, []) self.assertEqual(qs, result)
def test_conjoined_default_value(self): f = MultipleChoiceFilter() self.assertFalse(f.conjoined)