diff --git a/mapit/models.py b/mapit/models.py index 237f5dcd..15373b6e 100644 --- a/mapit/models.py +++ b/mapit/models.py @@ -9,9 +9,11 @@ from django.db.models.query import RawQuerySet from django.utils.encoding import smart_str from django.utils.functional import cached_property +from django.utils.translation import gettext as _ from mapit import countries from mapit.geometryserialiser import GeometrySerialiser +from mapit.middleware import ViewException def materialized(): @@ -44,6 +46,23 @@ def new(self): return None return latest[0] + def query_args(self, request, format): + try: + generation = int(request.GET.get('generation', 0)) + except ValueError: + raise ViewException(format, _('Bad generation specified'), 400) + if not generation: + generation = self.current().id + + try: + min_generation = int(request.GET.get('min_generation', 0)) + except ValueError: + raise ViewException(format, _('Bad min_generation specified'), 400) + if not min_generation: + min_generation = generation + + return generation, min_generation + class Generation(models.Model): @@ -138,23 +157,23 @@ def get_queryset(self): return super(AreaManager, self).get_queryset().select_related( 'type', 'country', 'parent_area').prefetch_related('countries') - def by_location(self, location, generation=None): + def by_location(self, location, generation=None, min_generation=None): if generation is None: generation = Generation.objects.current() + if min_generation is None: + min_generation = Generation.objects.current() if not location: return [] return Area.objects.filter( polygons__polygon__contains=location, - generation_low__lte=generation, generation_high__gte=generation + generation_low__lte=generation, generation_high__gte=min_generation ) - def by_postcode(self, postcode, generation=None): - if not generation: - generation = Generation.objects.current() + def by_postcode(self, postcode, generation, min_generation): return list(itertools.chain( - self.by_location(postcode.location, generation), + self.by_location(postcode.location, generation, min_generation), postcode.areas.filter( - generation_low__lte=generation, generation_high__gte=generation + generation_low__lte=generation, generation_high__gte=min_generation ) )) diff --git a/mapit/templates/mapit/api/postcode.html b/mapit/templates/mapit/api/postcode.html index 6781395e..e39018fe 100644 --- a/mapit/templates/mapit/api/postcode.html +++ b/mapit/templates/mapit/api/postcode.html @@ -19,11 +19,15 @@

{% trans "Optional query parameters" %}:
-
+
+
  • + {% blocktrans trimmed %} + min_generation, to return results since that generation. + {% endblocktrans %} +
  • {% include "mapit/api/postcode-example.html" %} diff --git a/mapit/tests/test_query_args.py b/mapit/tests/test_query_args.py index c8785f44..5090d201 100644 --- a/mapit/tests/test_query_args.py +++ b/mapit/tests/test_query_args.py @@ -130,3 +130,16 @@ def test_two_countries_in_query(self): generation_low__lte=self.active_generation.id, ) & (Q() | Q(country__code__in=['DE', 'FR']) | Q(countries__code__in=['DE', 'FR'])) ) + + def test_generation_manager_query_args(self): + gen, min_gen = Generation.objects.query_args( + FakeRequest({'generation': self.old_generation.id}), + 'json') + self.assertEqual(gen, self.old_generation.id) + self.assertEqual(min_gen, self.old_generation.id) + + gen, min_gen = Generation.objects.query_args( + FakeRequest({'min_generation': self.old_generation.id}), + 'json') + self.assertEqual(min_gen, self.old_generation.id) + self.assertEqual(gen, self.active_generation.id) diff --git a/mapit/tests/test_views.py b/mapit/tests/test_views.py index 2a083e92..3ca02fd8 100644 --- a/mapit/tests/test_views.py +++ b/mapit/tests/test_views.py @@ -11,6 +11,10 @@ class AreaViewsTest(TestCase): def setUp(self): + self.old_generation = Generation.objects.create( + active=True, + description="Test old generation", + ) self.generation = Generation.objects.create( active=True, description="Test generation", @@ -41,7 +45,7 @@ def setUp(self): self.small_area_1 = Area.objects.create( name="Small Area 1", type=self.small_type, - generation_low=self.generation, + generation_low=self.old_generation, generation_high=self.generation, ) @@ -52,10 +56,19 @@ def setUp(self): generation_high=self.generation, ) + self.small_area_3 = Area.objects.create( + name="Small Area 3", + type=self.small_type, + generation_low=self.old_generation, + generation_high=self.old_generation, + ) + polygon = Polygon(((-4, 51), (-4, 52), (-3, 52), (-3, 51), (-4, 51)), srid=4326) polygon.transform(settings.MAPIT_AREA_SRID) self.small_shape_1 = Geometry.objects.create( area=self.small_area_1, polygon=polygon) + self.small_shape_3 = Geometry.objects.create( + area=self.small_area_3, polygon=polygon) polygon = Polygon(((-3, 51), (-3, 52), (-2, 52), (-2, 51), (-3, 51)), srid=4326) polygon.transform(settings.MAPIT_AREA_SRID) @@ -123,6 +136,14 @@ def test_postcode_submission(self): response = self.client.post('/postcode/', {'pc': 'PO141NT.'}, follow=True) self.assertRedirects(response, '/postcode/PO141NT.html') + def test_postcode_endpoint(self): + response = self.client.get('/postcode/PO141NT') + content = get_content(response) + self.assertNotIn(self.small_area_3.id, content['areas']) + response = self.client.get('/postcode/PO141NT?min_generation=1') + content = get_content(response) + self.assertIn(str(self.small_area_3.id), content['areas']) + def test_json_links(self): id = self.big_area.id url = '/area/%d/covers.html?type=SML' % id diff --git a/mapit/views/areas.py b/mapit/views/areas.py index 40fafa0a..888e4742 100644 --- a/mapit/views/areas.py +++ b/mapit/views/areas.py @@ -60,19 +60,7 @@ def output_areas(request, title, format, areas, **kwargs): def query_args(request, format, type=None): - try: - generation = int(request.GET.get('generation', 0)) - except ValueError: - raise ViewException(format, _('Bad generation specified'), 400) - if not generation: - generation = Generation.objects.current().id - - try: - min_generation = int(request.GET.get('min_generation', 0)) - except ValueError: - raise ViewException(format, _('Bad min_generation specified'), 400) - if not min_generation: - min_generation = generation + generation, min_generation = Generation.objects.query_args(request, format) if type is None: type = request.GET.get('type', '') diff --git a/mapit/views/postcodes.py b/mapit/views/postcodes.py index b7209787..866a60ed 100644 --- a/mapit/views/postcodes.py +++ b/mapit/views/postcodes.py @@ -67,12 +67,11 @@ def postcode(request, postcode, format=None): if not is_valid_postcode(postcode): raise ViewException(format, "Postcode '%s' is not valid." % postcode, 400) postcode = get_object_or_404(Postcode, format=format, postcode=postcode) - try: - generation = int(request.GET['generation']) - except: - generation = Generation.objects.current() + + generation, min_generation = Generation.objects.query_args(request, format) + if not hasattr(countries, 'is_special_postcode') or not countries.is_special_postcode(postcode.postcode): - areas = list(add_codes(Area.objects.by_postcode(postcode, generation))) + areas = list(add_codes(Area.objects.by_postcode(postcode, generation, min_generation))) else: areas = []