Skip to content

Commit

Permalink
Fix and improve filter choices (#3812) (#3811)
Browse files Browse the repository at this point in the history
* fix and improve filter choices

* update changelog.rst

* Update docs/changelog.rst
  • Loading branch information
submarcos authored Oct 27, 2023
1 parent ad2e9aa commit 26d1e8e
Show file tree
Hide file tree
Showing 7 changed files with 44 additions and 33 deletions.
5 changes: 5 additions & 0 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ CHANGELOG
2.101.3+dev (XXXX-XX-XX)
------------------------

**Bug fixes**

- Fix: filters choices can raise exception in lists and not updated until application restart (#3812)


2.101.3 (2023-10-26)
------------------------

Expand Down
3 changes: 2 additions & 1 deletion geotrek/infrastructure/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class InfrastructureFilterSet(AltimetryAllGeometriesFilterSet, ValidTopologyFilt
description = CharFilter(label=_('Description'), lookup_expr='icontains')
implantation_year = MultipleChoiceFilter(choices=(('', '---------'),))
intervention_year = MultipleChoiceFilter(label=_("Intervention year"), method='filter_intervention_year',
choices=Intervention.objects.year_choices())
choices=(('', '---------'),))
category = MultipleChoiceFilter(label=_("Category"), field_name='type__type',
choices=INFRASTRUCTURE_TYPES)
trail = TopologyFilterTrail(label=_('Trail'), required=False)
Expand Down Expand Up @@ -44,3 +44,4 @@ def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.form.fields['implantation_year'].choices = Infrastructure.objects.implantation_year_choices()
self.form.fields['provider'].choices = Infrastructure.objects.provider_choices()
self.form.fields['intervention_year'].choices = Intervention.objects.year_choices()
12 changes: 10 additions & 2 deletions geotrek/maintenance/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ class InterventionFilterSet(AltimetryInterventionFilterSet, ZoningFilterSet, Str
ON_CHOICES += (('course', _("Outdoor Course")), ('site', _("Outdoor Site")),)

bbox = PolygonTopologyFilter(lookup_expr='intersects')
year = MultipleChoiceFilter(choices=Intervention.objects.year_choices(),
year = MultipleChoiceFilter(choices=(('', '---------'),),
field_name='date', lookup_expr='year', label=_("Year"))
on = ChoiceFilter(field_name='target_type__model', choices=ON_CHOICES, label=_("On"), empty_label=_("On"))
area_type = InterventionIntersectionFilterRestrictedAreaType(label=_('Restricted area type'), required=False,
Expand All @@ -146,12 +146,16 @@ class Meta(StructureRelatedFilterSet.Meta):
'status', 'type', 'stake', 'subcontracting', 'project', 'on',
]

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.form.fields['year'].choices = Intervention.objects.year_choices()


class ProjectFilterSet(StructureRelatedFilterSet):
bbox = PythonPolygonFilter(field_name='geom')
year = MultipleChoiceFilter(
label=_("Year of activity"), method='filter_year',
choices=lambda: Project.objects.year_choices() # Could change over time
choices=(('', '---------'),)
)
city = ProjectIntersectionFilterCity(label=_('City'), lookup_expr='intersects', required=False)
district = ProjectIntersectionFilterDistrict(label=_('District'), lookup_expr='intersects', required=False)
Expand All @@ -170,3 +174,7 @@ def filter_year(self, qs, name, values):
for value in values:
q |= Q(begin_year__lte=value, end_year__gte=value)
return qs.filter(q)

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.form.fields['year'].choices = Project.objects.year_choices()
5 changes: 3 additions & 2 deletions geotrek/maintenance/managers.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@

class InterventionManager(NoDeleteManager):
def year_choices(self):
return self.existing().filter(date__isnull=False).annotate(year=ExtractYear('date')) \
.order_by('-year').distinct().values_list('year', 'year')
values = self.existing().filter(date__isnull=False).annotate(year=ExtractYear('date')) \
.order_by('-year').distinct().values_list('year', flat=True)
return [(year, year) for year in values]


class ProjectManager(NoDeleteManager):
Expand Down
3 changes: 2 additions & 1 deletion geotrek/signage/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class SignageFilterSet(AltimetryPointFilterSet, ValidTopologyFilterSet, ZoningFi
description = CharFilter(label=_('Description'), lookup_expr='icontains')
implantation_year = MultipleChoiceFilter(choices=(('', '---------'),))
intervention_year = MultipleChoiceFilter(label=_("Intervention year"), method='filter_intervention_year',
choices=Intervention.objects.year_choices())
choices=(('', '---------'),))
trail = TopologyFilterTrail(label=_('Trail'), required=False)
provider = ChoiceFilter(
field_name='provider',
Expand All @@ -48,6 +48,7 @@ def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.form.fields['implantation_year'].choices = Signage.objects.implantation_year_choices()
self.form.fields['provider'].choices = Signage.objects.provider_choices()
self.form.fields['intervention_year'].choices = Intervention.objects.year_choices()

def filter_intervention_year(self, qs, name, value):
signage_ct = ContentType.objects.get_for_model(Signage)
Expand Down
18 changes: 2 additions & 16 deletions geotrek/tourism/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,20 +43,6 @@ class Meta(StructureRelatedFilterSet.Meta):
]


class AfterFilter(django_filters.DateFilter):
def filter(self, qs, value):
if not value:
return qs
return qs.filter(end_date__gte=value)


class BeforeFilter(django_filters.DateFilter):
def filter(self, qs, value):
if not value:
return qs
return qs.filter(begin_date__lte=value)


class CompletedFilter(django_filters.BooleanFilter):
"""
Filter events with end_date in past (event completed)
Expand All @@ -80,8 +66,8 @@ def filter(self, qs, value):


class TouristicEventFilterSet(ZoningFilterSet, StructureRelatedFilterSet):
after = AfterFilter(label=_("After"))
before = BeforeFilter(label=_("Before"))
after = django_filters.DateFilter(label=_("After"), lookup_expr='gte', field_name='end_date')
before = django_filters.DateFilter(label=_("Before"), lookup_expr='lte', field_name='begin_date')
completed = CompletedFilter(label=_("Completed"))
provider = ChoiceFilter(
field_name='provider',
Expand Down
31 changes: 20 additions & 11 deletions geotrek/tourism/tests/test_filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@

from geotrek.tourism.tests.factories import TouristicEventFactory
from geotrek.tourism.models import TouristicEvent
from geotrek.tourism.filters import CompletedFilter, BeforeFilter, AfterFilter
from geotrek.tourism.filters import CompletedFilter, TouristicEventFilterSet


class FilterList(TestCase):
class TouristicEventFilterSetTestCase(TestCase):
filter_class = TouristicEventFilterSet

@classmethod
def setUpTestData(cls):
# TouristicEvent : end_date = datetime.today()
Expand All @@ -14,17 +16,24 @@ def setUpTestData(cls):

def test_touristicevent_filter_completed(self):
cf = CompletedFilter()
bf = BeforeFilter()
af = AfterFilter()
# date <= Today (True) : completed
# date >= Today (False) : not completed
self.assertEqual(cf.filter(self.qs, False).count(), 1)
self.assertEqual(cf.filter(self.qs, True).count(), 0)

def test_before_filter(self):
filter = self.filter_class(data={'before': '2000-01-01'})
# Before : date <= date_of_filter
self.assertEqual(bf.filter(self.qs, '2000-01-01').count(), 0)
self.assertEqual(bf.filter(self.qs, '2150-01-01').count(), 1)
self.assertEqual(bf.filter(self.qs, '2300-01-01').count(), 1)
# After : date >= date_of_filter
self.assertEqual(af.filter(self.qs, '2000-01-01').count(), 1)
self.assertEqual(af.filter(self.qs, '2150-01-01').count(), 1)
self.assertEqual(af.filter(self.qs, '2300-01-01').count(), 0)
self.assertEqual(filter.qs.count(), 0)
filter = self.filter_class(data={'before': '2150-01-01'})
self.assertEqual(filter.qs.count(), 1)
filter = self.filter_class(data={'before': '2300-01-01'})
self.assertEqual(filter.qs.count(), 1)

def test_after_filter(self):
filter = self.filter_class(data={'after': '2000-01-01'})
self.assertEqual(filter.qs.count(), 1)
filter = self.filter_class(data={'after': '2150-01-01'})
self.assertEqual(filter.qs.count(), 1)
filter = self.filter_class(data={'after': '2300-01-01'})
self.assertEqual(filter.qs.count(), 0)

0 comments on commit 26d1e8e

Please sign in to comment.