diff --git a/geotrek/common/mixins/managers.py b/geotrek/common/mixins/managers.py index 25bd7aa388..69e6baff7d 100644 --- a/geotrek/common/mixins/managers.py +++ b/geotrek/common/mixins/managers.py @@ -17,3 +17,13 @@ def get_queryset(self): # Filter out deleted objects def existing(self): return self.get_queryset().filter(deleted=False) + + +class ProviderChoicesMixin: + def provider_choices(self): + qs = self.get_queryset() + if hasattr(qs, "existing"): + qs = qs.existing() + values = qs.exclude(provider__exact='') \ + .distinct('provider').order_by("provider").values_list('provider', flat=True) + return tuple((value, value) for value in values) diff --git a/geotrek/core/filters.py b/geotrek/core/filters.py index 37ff16f426..9a2e941c4f 100644 --- a/geotrek/core/filters.py +++ b/geotrek/core/filters.py @@ -103,7 +103,7 @@ class PathFilterSet(AltimetryAllGeometriesFilterSet, ZoningFilterSet, StructureR field_name='provider', empty_label=_("Provider"), label=_("Provider"), - choices=Path.objects.provider_choices() + choices=(('', '---------'),) ) networks = ModelMultipleChoiceFilter(queryset=Network.objects.all().select_related("structure")) usages = ModelMultipleChoiceFilter(queryset=Usage.objects.all().select_related("structure")) @@ -114,6 +114,10 @@ class Meta(StructureRelatedFilterSet.Meta): fields = StructureRelatedFilterSet.Meta.fields + \ ['valid', 'networks', 'usages', 'comfort', 'stake', 'draft', 'provider'] + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.form.fields['provider'].choices = Path.objects.provider_choices() + class TrailFilterSet(AltimetryAllGeometriesFilterSet, ValidTopologyFilterSet, ZoningFilterSet, StructureRelatedFilterSet): """Trail filter set""" @@ -130,7 +134,7 @@ class TrailFilterSet(AltimetryAllGeometriesFilterSet, ValidTopologyFilterSet, Zo field_name='provider', empty_label=_("Provider"), label=_("Provider"), - choices=Trail.objects.provider_choices() + choices=(('', '---------'),) ) class Meta(StructureRelatedFilterSet.Meta): @@ -138,6 +142,10 @@ class Meta(StructureRelatedFilterSet.Meta): fields = StructureRelatedFilterSet.Meta.fields + \ ['name', 'category', 'departure', 'arrival', 'certification_labels', 'comments', 'provider'] + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.form.fields['provider'].choices = Trail.objects.provider_choices() + class TopologyFilterTrail(TopologyFilter): queryset = Trail.objects.existing() diff --git a/geotrek/core/managers.py b/geotrek/core/managers.py index b77c034c7a..143a28d224 100644 --- a/geotrek/core/managers.py +++ b/geotrek/core/managers.py @@ -1,10 +1,10 @@ from django.contrib.gis.db import models from geotrek.common.functions import Length -from geotrek.common.mixins.managers import NoDeleteManager +from geotrek.common.mixins.managers import NoDeleteManager, ProviderChoicesMixin -class PathManager(models.Manager): +class PathManager(models.Manager, ProviderChoicesMixin): # Use this manager when walking through FK/M2M relationships use_for_related_fields = True @@ -13,11 +13,6 @@ def get_queryset(self): """ return super().get_queryset().filter(visible=True).annotate(length_2d=Length('geom')) - def provider_choices(self): - providers = self.get_queryset().exclude(provider__exact='') \ - .distinct('provider').values_list('provider', 'provider') - return providers - class PathInvisibleManager(models.Manager): use_for_related_fields = True @@ -39,8 +34,5 @@ def get_queryset(self): return super().get_queryset().order_by('order') -class TrailManager(TopologyManager): - def provider_choices(self): - providers = self.get_queryset().existing().exclude(provider__exact='').order_by('provider') \ - .distinct('provider').values_list('provider', 'provider') - return providers +class TrailManager(TopologyManager, ProviderChoicesMixin): + pass diff --git a/geotrek/core/tests/test_views.py b/geotrek/core/tests/test_views.py index c8fa7ac5d4..5feb5728cf 100644 --- a/geotrek/core/tests/test_views.py +++ b/geotrek/core/tests/test_views.py @@ -19,6 +19,7 @@ from geotrek.authent.tests.base import AuthentFixturesTest from geotrek.core.models import Path, Trail, PathSource +from geotrek.core.filters import PathFilterSet, TrailFilterSet from geotrek.trekking.tests.factories import POIFactory, TrekFactory, ServiceFactory from geotrek.infrastructure.tests.factories import InfrastructureFactory @@ -873,3 +874,53 @@ def test_remove_poi(self): self.assertEqual(poi.deleted, False) self.assertAlmostEqual(1.5, poi.offset) + + +class PathFilterTest(CommonTest, AuthentFixturesTest): + factory = PathFactory + filterset = PathFilterSet + + def test_provider_filter_without_provider(self): + filter_set = PathFilterSet(data={}) + filter_form = filter_set.form + + self.assertTrue(filter_form.is_valid()) + self.assertEqual(0, filter_set.qs.count()) + + def test_provider_filter_with_providers(self): + path1 = PathFactory.create(provider='my_provider1') + path2 = PathFactory.create(provider='my_provider2') + + filter_set = PathFilterSet() + filter_form = filter_set.form + + self.assertIn('', filter_form.as_p()) + self.assertIn('', filter_form.as_p()) + + self.assertIn(path1, filter_set.qs) + self.assertIn(path2, filter_set.qs) + + +class TrailFilterTest(CommonTest, AuthentFixturesTest): + factory = TrailFactory + filterset = TrailFilterSet + + def test_provider_filter_without_provider(self): + filter_set = TrailFilterSet(data={}) + filter_form = filter_set.form + + self.assertTrue(filter_form.is_valid()) + self.assertEqual(0, filter_set.qs.count()) + + def test_provider_filter_with_providers(self): + trail1 = TrailFactory.create(provider='my_provider1') + trail2 = TrailFactory.create(provider='my_provider2') + + filter_set = TrailFilterSet() + filter_form = filter_set.form + + self.assertIn('', filter_form.as_p()) + self.assertIn('', filter_form.as_p()) + + self.assertIn(trail1, filter_set.qs) + self.assertIn(trail2, filter_set.qs) diff --git a/geotrek/infrastructure/filters.py b/geotrek/infrastructure/filters.py index a5aa4150c5..1a88cc1e33 100644 --- a/geotrek/infrastructure/filters.py +++ b/geotrek/infrastructure/filters.py @@ -24,7 +24,7 @@ class InfrastructureFilterSet(AltimetryAllGeometriesFilterSet, ValidTopologyFilt field_name='provider', empty_label=_("Provider"), label=_("Provider"), - choices=Infrastructure.objects.provider_choices() + choices=(('', '---------'),) ) class Meta(StructureRelatedFilterSet.Meta): @@ -43,3 +43,4 @@ def filter_intervention_year(self, qs, name, value): 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() diff --git a/geotrek/infrastructure/managers.py b/geotrek/infrastructure/managers.py index 09d8f0fbbd..7fba2faa8e 100644 --- a/geotrek/infrastructure/managers.py +++ b/geotrek/infrastructure/managers.py @@ -1,15 +1,10 @@ -from geotrek.common.mixins.managers import NoDeleteManager +from geotrek.common.mixins.managers import NoDeleteManager, ProviderChoicesMixin -class InfrastructureGISManager(NoDeleteManager): +class InfrastructureGISManager(NoDeleteManager, ProviderChoicesMixin): """ Override default typology mixin manager""" def implantation_year_choices(self): values = self.get_queryset().existing().filter(implantation_year__isnull=False)\ .order_by('-implantation_year').distinct('implantation_year') \ .values_list('implantation_year', flat=True) return tuple((value, value) for value in values) - - def provider_choices(self): - providers = self.get_queryset().existing().exclude(provider__exact='') \ - .distinct('provider').values_list('provider', 'provider') - return providers diff --git a/geotrek/infrastructure/tests/test_views.py b/geotrek/infrastructure/tests/test_views.py index b1ffa2371f..b01b336684 100755 --- a/geotrek/infrastructure/tests/test_views.py +++ b/geotrek/infrastructure/tests/test_views.py @@ -3,6 +3,7 @@ from geotrek.common.tests import CommonTest, GeotrekAPITestCase from geotrek.authent.tests.factories import PathManagerFactory from geotrek.infrastructure.models import (Infrastructure, INFRASTRUCTURE_TYPES) +from geotrek.infrastructure.filters import InfrastructureFilterSet from geotrek.core.tests.factories import PathFactory from geotrek.infrastructure.tests.factories import (InfrastructureFactory, InfrastructureNoPictogramFactory, InfrastructureTypeFactory, InfrastructureConditionFactory, @@ -116,3 +117,28 @@ def get_good_data(self): else: good_data['geom'] = 'POINT(0.42 0.666)' return good_data + + +class InfrastructureFilterTest(CommonTest): + factory = InfrastructureFactory + filterset = InfrastructureFilterSet + + def test_provider_filter_without_provider(self): + filter_set = InfrastructureFilterSet(data={}) + filter_form = filter_set.form + + self.assertTrue(filter_form.is_valid()) + self.assertEqual(0, filter_set.qs.count()) + + def test_provider_filter_with_providers(self): + infrastructure1 = InfrastructureFactory.create(provider='my_provider1') + infrastructure2 = InfrastructureFactory.create(provider='my_provider2') + + filter_set = InfrastructureFilterSet() + filter_form = filter_set.form + + self.assertIn('', filter_form.as_p()) + self.assertIn('', filter_form.as_p()) + + self.assertIn(infrastructure1, filter_set.qs) + self.assertIn(infrastructure2, filter_set.qs) diff --git a/geotrek/outdoor/filters.py b/geotrek/outdoor/filters.py index 12fc390a63..ab10c540e3 100644 --- a/geotrek/outdoor/filters.py +++ b/geotrek/outdoor/filters.py @@ -17,7 +17,7 @@ class SiteFilterSet(ZoningFilterSet, StructureRelatedFilterSet): field_name='provider', empty_label=_("Provider"), label=_("Provider"), - choices=Site.objects.provider_choices() + choices=(('', '---------'),) ) class Meta(StructureRelatedFilterSet.Meta): @@ -27,6 +27,10 @@ class Meta(StructureRelatedFilterSet.Meta): 'web_links', 'type', 'orientation', 'wind', 'provider' ] + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.form.fields['provider'].choices = Site.objects.provider_choices() + def filter_orientation(self, qs, name, values): q = Q() for value in values: @@ -58,7 +62,7 @@ class CourseFilterSet(ZoningFilterSet, StructureRelatedFilterSet): field_name='provider', empty_label=_("Provider"), label=_("Provider"), - choices=Course.objects.provider_choices() + choices=(('', '---------'),) ) class Meta(StructureRelatedFilterSet.Meta): @@ -69,6 +73,10 @@ class Meta(StructureRelatedFilterSet.Meta): 'height', 'provider' ] + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.form.fields['provider'].choices = Course.objects.provider_choices() + def filter_orientation(self, qs, name, values): q = Q() for value in values: diff --git a/geotrek/outdoor/managers.py b/geotrek/outdoor/managers.py index 6dc0d082db..c5d1ac0aa6 100644 --- a/geotrek/outdoor/managers.py +++ b/geotrek/outdoor/managers.py @@ -2,12 +2,11 @@ from django.db.models import Manager from mptt.managers import TreeManager +from geotrek.common.mixins.managers import ProviderChoicesMixin -class SiteManager(TreeManager): - def provider_choices(self): - providers = self.get_queryset().exclude(provider__exact='').order_by('provider') \ - .distinct('provider').values_list('provider', 'provider') - return providers + +class SiteManager(TreeManager, ProviderChoicesMixin): + pass class CourseOrderedChildManager(models.Manager): @@ -18,8 +17,5 @@ def get_queryset(self): return super(CourseOrderedChildManager, self).get_queryset().select_related('parent', 'child') -class CourseManager(Manager): - def provider_choices(self): - providers = self.get_queryset().exclude(provider__exact='').order_by('provider') \ - .distinct('provider').values_list('provider', 'provider') - return providers +class CourseManager(Manager, ProviderChoicesMixin): + pass diff --git a/geotrek/outdoor/tests/test_views.py b/geotrek/outdoor/tests/test_views.py index f478cd3974..64d0dc78fb 100644 --- a/geotrek/outdoor/tests/test_views.py +++ b/geotrek/outdoor/tests/test_views.py @@ -11,6 +11,7 @@ TargetPortalFactory) from geotrek.outdoor import views as course_views from geotrek.outdoor.models import Site +from geotrek.outdoor.filters import SiteFilterSet, CourseFilterSet from geotrek.outdoor.tests.factories import CourseFactory, SiteFactory from geotrek.tourism.tests.test_views import PNG_BLACK_PIXEL from geotrek.trekking.tests.factories import POIFactory @@ -161,3 +162,53 @@ def test_delete_site(self): self.assertEqual(response.status_code, 302) self.assertEqual(Site.objects.count(), 1) self.assertEqual(Site.objects.filter(pk=site_1.pk).exists(), True) + + +class SiteFilterTest(TestCase): + factory = SiteFactory + filterset = SiteFilterSet + + def test_provider_filter_without_provider(self): + filter_set = SiteFilterSet(data={}) + filter_form = filter_set.form + + self.assertTrue(filter_form.is_valid()) + self.assertEqual(0, filter_set.qs.count()) + + def test_provider_filter_with_providers(self): + site1 = SiteFactory.create(provider='my_provider1') + site2 = SiteFactory.create(provider='my_provider2') + + filter_set = SiteFilterSet() + filter_form = filter_set.form + + self.assertIn('', filter_form.as_p()) + self.assertIn('', filter_form.as_p()) + + self.assertIn(site1, filter_set.qs) + self.assertIn(site2, filter_set.qs) + + +class CourseFilterTest(TestCase): + factory = CourseFactory + filterset = CourseFilterSet + + def test_provider_filter_without_provider(self): + filter_set = CourseFilterSet(data={}) + filter_form = filter_set.form + + self.assertTrue(filter_form.is_valid()) + self.assertEqual(0, filter_set.qs.count()) + + def test_provider_filter_with_providers(self): + course1 = CourseFactory.create(provider='my_provider1') + course2 = CourseFactory.create(provider='my_provider2') + + filter_set = CourseFilterSet() + filter_form = filter_set.form + + self.assertIn('', filter_form.as_p()) + self.assertIn('', filter_form.as_p()) + + self.assertIn(course1, filter_set.qs) + self.assertIn(course2, filter_set.qs) diff --git a/geotrek/sensitivity/filters.py b/geotrek/sensitivity/filters.py index 0b631e1b8c..27f277936d 100644 --- a/geotrek/sensitivity/filters.py +++ b/geotrek/sensitivity/filters.py @@ -13,9 +13,13 @@ class SensitiveAreaFilterSet(StructureRelatedFilterSet): field_name='provider', empty_label=_("Provider"), label=_("Provider"), - choices=SensitiveArea.objects.provider_choices() + choices=(('', '---------'),) ) + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.form.fields['provider'].choices = SensitiveArea.objects.provider_choices() + class Meta(StructureRelatedFilterSet.Meta): model = SensitiveArea fields = StructureRelatedFilterSet.Meta.fields + [ diff --git a/geotrek/sensitivity/managers.py b/geotrek/sensitivity/managers.py index 16b5c5bac6..f363eb40b3 100644 --- a/geotrek/sensitivity/managers.py +++ b/geotrek/sensitivity/managers.py @@ -1,8 +1,5 @@ -from geotrek.common.mixins.managers import NoDeleteManager +from geotrek.common.mixins.managers import NoDeleteManager, ProviderChoicesMixin -class SensitiveAreaManager(NoDeleteManager): - def provider_choices(self): - providers = self.get_queryset().existing().exclude(provider__exact='') \ - .distinct('provider').values_list('provider', 'provider') - return providers +class SensitiveAreaManager(NoDeleteManager, ProviderChoicesMixin): + pass diff --git a/geotrek/sensitivity/tests/test_views.py b/geotrek/sensitivity/tests/test_views.py index f0ebb92a9c..e4a7cad644 100644 --- a/geotrek/sensitivity/tests/test_views.py +++ b/geotrek/sensitivity/tests/test_views.py @@ -16,6 +16,7 @@ MultiPolygonSensitiveAreaFactory ) from geotrek.sensitivity.models import SportPractice +from geotrek.sensitivity.filters import SensitiveAreaFilterSet class SensitiveAreaViewsSameStructureTests(AuthentFixturesTest): @@ -371,3 +372,28 @@ def test_openair_list(self): '\n' 'AC ZSM\n' self.assertContains(response, expected_response) + + +class SensitiveAreaFilterTest(TestCase): + factory = SensitiveAreaFactory + filterset = SensitiveAreaFilterSet + + def test_provider_filter_without_provider(self): + filter_set = SensitiveAreaFilterSet(data={}) + filter_form = filter_set.form + + self.assertTrue(filter_form.is_valid()) + self.assertEqual(0, filter_set.qs.count()) + + def test_provider_filter_with_providers(self): + sensitive_area1 = SensitiveAreaFactory.create(provider='my_provider1') + sensitive_area2 = SensitiveAreaFactory.create(provider='my_provider2') + + filter_set = SensitiveAreaFilterSet() + filter_form = filter_set.form + + self.assertIn('', filter_form.as_p()) + self.assertIn('', filter_form.as_p()) + + self.assertIn(sensitive_area1, filter_set.qs) + self.assertIn(sensitive_area2, filter_set.qs) diff --git a/geotrek/signage/filters.py b/geotrek/signage/filters.py index 879a0a8c6e..431360027f 100644 --- a/geotrek/signage/filters.py +++ b/geotrek/signage/filters.py @@ -35,7 +35,7 @@ class SignageFilterSet(AltimetryPointFilterSet, ValidTopologyFilterSet, ZoningFi field_name='provider', empty_label=_("Provider"), label=_("Provider"), - choices=Signage.objects.provider_choices() + choices=(('', '---------'),) ) class Meta(StructureRelatedFilterSet.Meta): @@ -47,6 +47,7 @@ class Meta(StructureRelatedFilterSet.Meta): 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() def filter_intervention_year(self, qs, name, value): signage_ct = ContentType.objects.get_for_model(Signage) diff --git a/geotrek/signage/managers.py b/geotrek/signage/managers.py index 7e82df155e..55d0f7fb17 100644 --- a/geotrek/signage/managers.py +++ b/geotrek/signage/managers.py @@ -1,15 +1,10 @@ -from geotrek.common.mixins.managers import NoDeleteManager +from geotrek.common.mixins.managers import NoDeleteManager, ProviderChoicesMixin -class SignageGISManager(NoDeleteManager): +class SignageGISManager(NoDeleteManager, ProviderChoicesMixin): """ Override default typology mixin manager, and filter by type. """ def implantation_year_choices(self): values = self.get_queryset().existing().filter(implantation_year__isnull=False)\ .order_by('-implantation_year').distinct('implantation_year') \ .values_list('implantation_year', flat=True) return tuple((value, value) for value in values) - - def provider_choices(self): - providers = self.get_queryset().existing().exclude(provider__exact='') \ - .distinct('provider').values_list('provider', 'provider') - return providers diff --git a/geotrek/signage/tests/test_views.py b/geotrek/signage/tests/test_views.py index 6548859e03..9f826f9f95 100755 --- a/geotrek/signage/tests/test_views.py +++ b/geotrek/signage/tests/test_views.py @@ -463,6 +463,26 @@ def test_implantation_year_filter_with_str(self): self.assertIn(i, filter_set.qs) self.assertIn(i2, filter_set.qs) + def test_provider_filter_without_provider(self): + filter_set = SignageFilterSet(data={}) + filter_form = filter_set.form + + self.assertTrue(filter_form.is_valid()) + self.assertEqual(0, filter_set.qs.count()) + + def test_provider_filter_with_providers(self): + signage1 = SignageFactory.create(provider='my_provider1') + signage2 = SignageFactory.create(provider='my_provider2') + + filter_set = SignageFilterSet() + filter_form = filter_set.form + + self.assertIn('', filter_form.as_p()) + self.assertIn('', filter_form.as_p()) + + self.assertIn(signage1, filter_set.qs) + self.assertIn(signage2, filter_set.qs) + class BladeFilterSetTest(TestCase): factory = BladeFactory diff --git a/geotrek/tourism/filters.py b/geotrek/tourism/filters.py index 88cb7007ec..7ab4177d23 100644 --- a/geotrek/tourism/filters.py +++ b/geotrek/tourism/filters.py @@ -27,9 +27,13 @@ class TouristicContentFilterSet(ZoningFilterSet, StructureRelatedFilterSet): field_name='provider', empty_label=_("Provider"), label=_("Provider"), - choices=TouristicContent.objects.provider_choices() + choices=(('', '---------'),) ) + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.form.fields['provider'].choices = TouristicContent.objects.provider_choices() + class Meta(StructureRelatedFilterSet.Meta): model = TouristicContent fields = StructureRelatedFilterSet.Meta.fields + [ @@ -83,9 +87,13 @@ class TouristicEventFilterSet(ZoningFilterSet, StructureRelatedFilterSet): field_name='provider', empty_label=_("Provider"), label=_("Provider"), - choices=TouristicEvent.objects.provider_choices() + choices=(('', '---------'),) ) + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.form.fields['provider'].choices = TouristicEvent.objects.provider_choices() + class Meta(StructureRelatedFilterSet.Meta): model = TouristicEvent fields = StructureRelatedFilterSet.Meta.fields + [ diff --git a/geotrek/tourism/managers.py b/geotrek/tourism/managers.py index 937b48719c..d4c2e92884 100644 --- a/geotrek/tourism/managers.py +++ b/geotrek/tourism/managers.py @@ -2,7 +2,7 @@ from django.db.models import Q from modeltranslation.manager import MultilingualManager -from geotrek.common.mixins.managers import NoDeleteManager +from geotrek.common.mixins.managers import NoDeleteManager, ProviderChoicesMixin class TouristicContentTypeFilteringManager(MultilingualManager): @@ -61,15 +61,9 @@ def get_queryset(self): return super().get_queryset().filter(in_list=2) -class TouristicContentManager(NoDeleteManager): - def provider_choices(self): - providers = self.get_queryset().existing().exclude(provider__exact='') \ - .distinct('provider').values_list('provider', 'provider') - return providers +class TouristicContentManager(NoDeleteManager, ProviderChoicesMixin): + pass -class TouristicEventManager(NoDeleteManager): - def provider_choices(self): - providers = self.get_queryset().existing().order_by('provider').exclude(provider__exact='') \ - .distinct('provider').values_list('provider', 'provider') - return providers +class TouristicEventManager(NoDeleteManager, ProviderChoicesMixin): + pass diff --git a/geotrek/tourism/tests/test_views.py b/geotrek/tourism/tests/test_views.py index 1aa9c4811a..86559b244e 100644 --- a/geotrek/tourism/tests/test_views.py +++ b/geotrek/tourism/tests/test_views.py @@ -30,6 +30,7 @@ TouristicContentType1Factory, TouristicContentType2Factory, TouristicEventFactory) +from geotrek.tourism.filters import TouristicContentFilterSet, TouristicEventFilterSet from geotrek.trekking.tests import factories as trekking_factories from geotrek.trekking.tests.base import TrekkingManagerTest from geotrek.zoning.tests import factories as zoning_factories @@ -566,3 +567,53 @@ def test_geojson(self): self.assertEqual(result['features'][0]['type'], 'Feature') self.assertEqual(result['features'][0]['geometry']['type'], 'Point') self.assertEqual(result['features'][0]['properties']['name'], desk.name) + + +class TouristicContentFilterTest(TestCase): + factory = TouristicContentFactory + filterset = TouristicContentFilterSet + + def test_provider_filter_without_provider(self): + filter_set = TouristicContentFilterSet(data={}) + filter_form = filter_set.form + + self.assertTrue(filter_form.is_valid()) + self.assertEqual(0, filter_set.qs.count()) + + def test_provider_filter_with_providers(self): + touristic_content1 = TouristicContentFactory.create(provider='my_provider1') + touristic_content2 = TouristicContentFactory.create(provider='my_provider2') + + filter_set = TouristicContentFilterSet() + filter_form = filter_set.form + + self.assertIn('', filter_form.as_p()) + self.assertIn('', filter_form.as_p()) + + self.assertIn(touristic_content1, filter_set.qs) + self.assertIn(touristic_content2, filter_set.qs) + + +class TouristicEventFilterTest(TestCase): + factory = TouristicEventFactory + filterset = TouristicEventFilterSet + + def test_provider_filter_without_provider(self): + filter_set = TouristicEventFilterSet(data={}) + filter_form = filter_set.form + + self.assertTrue(filter_form.is_valid()) + self.assertEqual(0, filter_set.qs.count()) + + def test_provider_filter_with_providers(self): + touristic_event1 = TouristicEventFactory.create(provider='my_provider1') + touristic_event2 = TouristicEventFactory.create(provider='my_provider2') + + filter_set = TouristicEventFilterSet() + filter_form = filter_set.form + + self.assertIn('', filter_form.as_p()) + self.assertIn('', filter_form.as_p()) + + self.assertIn(touristic_event1, filter_set.qs) + self.assertIn(touristic_event2, filter_set.qs) diff --git a/geotrek/trekking/filters.py b/geotrek/trekking/filters.py index bdf58e7d3a..fb7e0031e8 100644 --- a/geotrek/trekking/filters.py +++ b/geotrek/trekking/filters.py @@ -13,7 +13,7 @@ class TrekFilterSet(AltimetryAllGeometriesFilterSet, ValidTopologyFilterSet, Zon field_name='provider', empty_label=_("Provider"), label=_("Provider"), - choices=Trek.objects.provider_choices() + choices=(('', '---------'),) ) class Meta(StructureRelatedFilterSet.Meta): @@ -24,6 +24,10 @@ class Meta(StructureRelatedFilterSet.Meta): 'source', 'portal', 'reservation_system', 'provider' ] + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.form.fields['provider'].choices = Trek.objects.provider_choices() + class POITrekFilter(TopologyFilter): queryset = Trek.objects.existing() @@ -35,9 +39,13 @@ class POIFilterSet(AltimetryPointFilterSet, ValidTopologyFilterSet, ZoningFilter field_name='provider', empty_label=_("Provider"), label=_("Provider"), - choices=POI.objects.provider_choices() + choices=(('', '---------'),) ) + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.form.fields['provider'].choices = POI.objects.provider_choices() + class Meta(StructureRelatedFilterSet.Meta): model = POI fields = StructureRelatedFilterSet.Meta.fields + [ @@ -50,9 +58,13 @@ class ServiceFilterSet(AltimetryPointFilterSet, ValidTopologyFilterSet, ZoningFi field_name='provider', empty_label=_("Provider"), label=_("Provider"), - choices=Service.objects.provider_choices() + choices=(('', '---------'),) ) + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.form.fields['provider'].choices = Service.objects.provider_choices() + class Meta(StructureRelatedFilterSet.Meta): model = Service fields = StructureRelatedFilterSet.Meta.fields + ['type', 'provider'] diff --git a/geotrek/trekking/managers.py b/geotrek/trekking/managers.py index 15669a7977..8be2dcfe4b 100644 --- a/geotrek/trekking/managers.py +++ b/geotrek/trekking/managers.py @@ -1,6 +1,6 @@ from django.contrib.gis.db import models -from geotrek.common.mixins.managers import NoDeleteManager +from geotrek.common.mixins.managers import NoDeleteManager, ProviderChoicesMixin from geotrek.core.managers import TopologyManager @@ -14,11 +14,8 @@ def get_queryset(self): return qs.exclude(parent__deleted=True).exclude(child__deleted=True) -class TrekManager(TopologyManager): - def provider_choices(self): - providers = self.get_queryset().existing().order_by('provider').distinct('provider') \ - .exclude(provider__exact='').values_list('provider', 'provider') - return providers +class TrekManager(TopologyManager, ProviderChoicesMixin): + pass class TrekRelationshipManager(models.Manager): @@ -36,15 +33,9 @@ def get_queryset(self): return super().get_queryset().select_related('category') -class POIManager(NoDeleteManager): - def provider_choices(self): - providers = self.get_queryset().existing().exclude(provider__exact='') \ - .distinct('provider').values_list('provider', 'provider') - return providers +class POIManager(NoDeleteManager, ProviderChoicesMixin): + pass -class ServiceManager(NoDeleteManager): - def provider_choices(self): - providers = self.get_queryset().existing().exclude(provider__exact='') \ - .distinct('provider').values_list('provider', 'provider') - return providers +class ServiceManager(NoDeleteManager, ProviderChoicesMixin): + pass diff --git a/geotrek/trekking/tests/test_views.py b/geotrek/trekking/tests/test_views.py index f29bfe0e74..60c77ce5c3 100755 --- a/geotrek/trekking/tests/test_views.py +++ b/geotrek/trekking/tests/test_views.py @@ -37,6 +37,7 @@ # Make sur to register Trek model from geotrek.trekking import urls # NOQA from geotrek.trekking import views as trekking_views +from geotrek.trekking.filters import TrekFilterSet, POIFilterSet, ServiceFilterSet from geotrek.zoning.tests.factories import DistrictFactory, CityFactory from .base import TrekkingManagerTest from .factories import (POIFactory, POITypeFactory, TrekFactory, TrekWithPOIsFactory, @@ -1653,3 +1654,78 @@ def test_delete_infrastructure_refreshes_pdf(self, mock_get): trek.infrastructures[0].delete() trek = Trek.objects.get(pk=self.trek.pk) self.assertFalse(is_file_uptodate(trek.get_map_image_path(), trek.get_date_update())) + + +class TrekFilterTest(TestCase): + factory = TrekFactory + filterset = TrekFilterSet + + def test_provider_filter_without_provider(self): + filter_set = TrekFilterSet(data={}) + filter_form = filter_set.form + + self.assertTrue(filter_form.is_valid()) + self.assertEqual(0, filter_set.qs.count()) + + def test_provider_filter_with_providers(self): + trek1 = TrekFactory.create(provider='my_provider1') + trek2 = TrekFactory.create(provider='my_provider2') + + filter_set = TrekFilterSet() + filter_form = filter_set.form + + self.assertIn('', filter_form.as_p()) + self.assertIn('', filter_form.as_p()) + + self.assertIn(trek1, filter_set.qs) + self.assertIn(trek2, filter_set.qs) + + +class POIFilterTest(TestCase): + factory = POIFactory + filterset = POIFilterSet + + def test_provider_filter_without_provider(self): + filter_set = POIFilterSet(data={}) + filter_form = filter_set.form + + self.assertTrue(filter_form.is_valid()) + self.assertEqual(0, filter_set.qs.count()) + + def test_provider_filter_with_providers(self): + poi1 = POIFactory.create(provider='my_provider1') + poi2 = POIFactory.create(provider='my_provider2') + + filter_set = POIFilterSet() + filter_form = filter_set.form + + self.assertIn('', filter_form.as_p()) + self.assertIn('', filter_form.as_p()) + + self.assertIn(poi1, filter_set.qs) + self.assertIn(poi2, filter_set.qs) + + +class ServiceFilterTest(TestCase): + factory = ServiceFactory + filterset = ServiceFilterSet + + def test_provider_filter_without_provider(self): + filter_set = ServiceFilterSet(data={}) + filter_form = filter_set.form + + self.assertTrue(filter_form.is_valid()) + self.assertEqual(0, filter_set.qs.count()) + + def test_provider_filter_with_providers(self): + service1 = ServiceFactory.create(provider='my_provider1') + service2 = ServiceFactory.create(provider='my_provider2') + + filter_set = ServiceFilterSet() + filter_form = filter_set.form + + self.assertIn('', filter_form.as_p()) + self.assertIn('', filter_form.as_p()) + + self.assertIn(service1, filter_set.qs) + self.assertIn(service2, filter_set.qs)