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 = []