From 530f0e7c8edbea699c84ef759364c2e51c3fd72f Mon Sep 17 00:00:00 2001 From: Benjamin Dauvergne Date: Mon, 12 Jul 2021 13:16:28 +0200 Subject: [PATCH 2/2] base_adresse: add lat/lon/type to address'id to get by id through reverse (#55522) --- passerelle/apps/base_adresse/models.py | 35 +++++++++++++++++++------- tests/test_base_adresse.py | 28 +++++++++++++++++---- 2 files changed, 49 insertions(+), 14 deletions(-) diff --git a/passerelle/apps/base_adresse/models.py b/passerelle/apps/base_adresse/models.py index 25977151..62837179 100644 --- a/passerelle/apps/base_adresse/models.py +++ b/passerelle/apps/base_adresse/models.py @@ -87,7 +87,9 @@ class BaseAdresse(BaseResource): value = value[len(house_number) :].strip() result['address']['road'] = value elif prop == 'id': - result['id'] = value + result['ban_id'] = value + result['id'] = '%s~%s~%s' % (value, result['lat'], result['lon']) + result['id'] = '%s~%s' % (result['id'], result['text']) return result @endpoint( @@ -117,7 +119,7 @@ class BaseAdresse(BaseResource): self, request, id=None, q=None, zipcode='', citycode=None, lat=None, lon=None, page_limit=5 ): if id is not None: - return self.get_by_id(request, id=id) + return self.get_by_id(request, id=id, citycode=citycode) if not q: return {'data': []} @@ -155,20 +157,35 @@ class BaseAdresse(BaseResource): data = self.format_address_data(feature) result.append(data) address, created = AddressCacheModel.objects.get_or_create( - api_id=data['id'], defaults={'data': data} + api_id=data['id'][:30], defaults={'data': data} ) if not created: address.update_timestamp() return {'data': result} - def get_by_id(self, request, id): + def get_by_id(self, request, id, citycode=None): try: - address = AddressCacheModel.objects.get(api_id=id) + ban_id, lat, lon, q = id.split('~', 4) + except ValueError: # retrocompatibility with raw BAN id + ban_id = id + lat, lon, q = None, None, None + # Try cache + try: + address = AddressCacheModel.objects.get(api_id=id[:30]) except AddressCacheModel.DoesNotExist: - return {'err': _('Address ID not found')} - address.update_timestamp() - return {'data': [address.data]} + pass + else: + address.update_timestamp() + return {'data': [address.data]} + # Use search with label as q and lat/lon as geographic hint + if q and lat and lon: + results = self.addresses(request, q=q, lat=lat, lon=lon, citycode=citycode)['data'] + for result in results: # match by id if possible + if result['ban_id'] == ban_id: + return {'data': [result]} + self.logger.error('get_by_id: id %s was not found', id) + return {'err': _('Address ID not found')} @endpoint( pattern='(?P.+)?$', @@ -225,7 +242,7 @@ class BaseAdresse(BaseResource): continue # skip unknown result = self.format_address_data(feature) address, created = AddressCacheModel.objects.get_or_create( - api_id=result['id'], defaults={'data': result} + api_id=result['id'][:30], defaults={'data': result} ) if not created: address.update_timestamp() diff --git a/tests/test_base_adresse.py b/tests/test_base_adresse.py index 18f90f36..80e0abc9 100644 --- a/tests/test_base_adresse.py +++ b/tests/test_base_adresse.py @@ -797,7 +797,7 @@ def test_base_adresse_addresses(mocked_get, app, base_adresse): assert data['lon'] == '-0.593775' assert data['display_name'] == 'Rue Roger Halope 49000 Angers' assert data['text'] == 'Rue Roger Halope 49000 Angers' - assert data['id'] == '49007_6950_be54bd' + assert data['id'] == '49007_6950_be54bd~47.474633~-0.593775~Rue Roger Halope 49000 Angers' assert data['address']['city'] == 'Angers' assert data['address']['postcode'] == '49000' assert data['address']['citycode'] == '49007' @@ -833,7 +833,7 @@ def test_base_adresse_addresses_qs_coordinates(mocked_get, app, base_adresse_coo assert 'lon=43' in mocked_get.call_args[0][0] -def test_base_adresse_addresses_cache(app, base_adresse, mock_api_adresse_data_gouv_fr_search): +def test_base_adresse_addresses_cache(app, base_adresse, mock_api_adresse_data_gouv_fr_search, caplog): resp = app.get('/base-adresse/%s/addresses?q=plop' % base_adresse.slug) assert mock_api_adresse_data_gouv_fr_search.call['count'] == 1 @@ -841,7 +841,7 @@ def test_base_adresse_addresses_cache(app, base_adresse, mock_api_adresse_data_g assert data['text'] == 'Rue Roger Halope 49000 Angers' api_id = data['id'] - assert AddressCacheModel.objects.filter(api_id=api_id).exists() + assert AddressCacheModel.objects.filter(api_id=api_id[:30]).exists() assert AddressCacheModel.objects.count() == 1 resp = app.get('/base-adresse/%s/addresses?id=%s' % (base_adresse.slug, api_id)) @@ -851,6 +851,21 @@ def test_base_adresse_addresses_cache(app, base_adresse, mock_api_adresse_data_g resp = app.get('/base-adresse/%s/addresses?q=plop' % base_adresse.slug) assert AddressCacheModel.objects.count() == 1 # no new object has been created + assert mock_api_adresse_data_gouv_fr_search.call['count'] == 2 + + # no cache + AddressCacheModel.objects.all().delete() + resp = app.get('/base-adresse/%s/addresses?id=%s' % (base_adresse.slug, api_id)) + assert AddressCacheModel.objects.count() == 1 + assert mock_api_adresse_data_gouv_fr_search.call['count'] == 3 + assert data['text'] == 'Rue Roger Halope 49000 Angers' + assert 'address' in data + + # no cache and id has changed + AddressCacheModel.objects.all().delete() + api_id = '49007_XXXX_be54bd~47.474633~-0.593775~Rue%20Roger%20Halope%2049000%20Angers' + resp = app.get('/base-adresse/%s/addresses?id=%s' % (base_adresse.slug, api_id)) + assert resp.json['err'] == 'Address ID not found' def test_base_adresse_addresses_cache_err(app, base_adresse, mock_api_adresse_data_gouv_fr_search): @@ -882,7 +897,10 @@ def test_base_adresse_addresses_clean_cache(app, base_adresse, freezer, mock_api assert AddressCacheModel.objects.count() == 1 freezer.move_to(datetime.timedelta(hours=1, seconds=1)) - resp = app.get('/base-adresse/%s/addresses?id=%s' % (base_adresse.slug, '49007_6950_be54bd')) + resp = app.get( + '/base-adresse/%s/addresses?id=%s' + % (base_adresse.slug, '49007_6950_be54bd~47.474633~-0.593775~Rue%20Roger%20Halope%2049000%20Angers') + ) call_command('cron', 'hourly') assert AddressCacheModel.objects.count() == 1 @@ -924,7 +942,7 @@ def test_base_adresse_reverse_cache( assert data['text'] == 'Rue Roger Halope 49000 Angers' api_id = data['id'] - assert AddressCacheModel.objects.filter(api_id=api_id).exists() + assert AddressCacheModel.objects.filter(api_id=api_id[:30]).exists() assert AddressCacheModel.objects.count() == 1 first_timestamp = AddressCacheModel.objects.get().timestamp -- 2.32.0.rc0