Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhancements to Address #160

Open
wants to merge 2 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 28 additions & 5 deletions address/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
ReverseSingleRelatedObjectDescriptor as ForwardManyToOneDescriptor,
)

from . import settings


logger = logging.getLogger(__name__)

__all__ = ["Country", "State", "Locality", "Address", "AddressField"]
Expand All @@ -26,6 +29,7 @@ def _to_python(value):
state = value.get("state", "")
state_code = value.get("state_code", "")
locality = value.get("locality", "")
administrative_area_level_3 = value.get('administrative_area_level_3', None)
sublocality = value.get("sublocality", "")
postal_town = value.get("postal_town", "")
postal_code = value.get("postal_code", "")
Expand All @@ -48,6 +52,21 @@ def _to_python(value):
if not locality and postal_town:
locality = postal_town

# Some locations doesn't have locality but having administrative_area_level_3, which both are representing city
# according to google: https://developers.google.com/maps/documentation/places/web-service/supported_types#table3
if not locality and administrative_area_level_3:
locality = administrative_area_level_3

if settings.ALLOW_UNKNOWN_STATES and country and locality and not state:
# address geocoded as Country and City without State
# handling case like "Copenhagen, Denmark"
state = 'UNKNOWN'
value['state_code'] = 'UKWN'

# This can happen if the user types in a value into the input then enter without selecting from the list.
if not settings.ALLOW_DUMMY_ADDRESSES and not country and not state_code and not locality:
raise ValidationError("Please choose from one of the location options in the dropdown.")

# If we have an inconsistent set of value bail out now.
if (country or state or locality) and not (country and state and locality):
raise InconsistentDictError
Expand All @@ -70,10 +89,13 @@ def _to_python(value):
state_obj = State.objects.get(name=state, country=country_obj)
except State.DoesNotExist:
if state:
if len(state_code) > State._meta.get_field("code").max_length:
if state_code != state:
raise ValueError("Invalid state code (too long): %s" % state_code)
state_code = ""
state_code_max_length = State._meta.get_field("code").max_length
if len(state_code) > state_code_max_length:
logger.warning(f'Trimming too long state_code {state_code} to {state_code_max_length} char only'
f' for raw value: {raw}')
# This is very odd case, raising error will not help as user has no choice to fix data
# best is to trim value to max allowed, example for this case: "Chum Phae Khon Kaen Thailand"
state_code = state_code[:state_code_max_length]
state_obj = State.objects.create(name=state, code=state_code, country=country_obj)
else:
state_obj = None
Expand Down Expand Up @@ -147,7 +169,8 @@ def to_python(value):
try:
return _to_python(value)
except InconsistentDictError:
return Address.objects.create(raw=value["raw"])
if settings.ALLOW_DUMMY_ADDRESSES:
return Address.objects.create(raw=value["raw"])

# Not in any of the formats I recognise.
raise ValidationError("Invalid address value.")
Expand Down
9 changes: 9 additions & 0 deletions address/settings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from django.conf import settings

# Some counties doesn't have "state" value so google return locality but not no state
# Set this to true and it will create dummy state
ALLOW_UNKNOWN_STATES = getattr(settings, 'ALLOW_UNKNOWN_STATES', False)

# Set this to false so only valid address is saved, allowing dummy addresses means
# accepting Address with only `raw` value is filled
ALLOW_DUMMY_ADDRESSES = getattr(settings, 'ALLOW_UNKNOWN_STATES', True)
3 changes: 2 additions & 1 deletion address/static/address/js/address.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ $(function () {
'country',
'country_code',
'locality',
'administrative_area_level_3',
'postal_code',
'postal_town',
'route',
Expand All @@ -29,4 +30,4 @@ $(function () {
}
});
});
});
});
3 changes: 2 additions & 1 deletion address/tests/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,8 @@ def test_assignment_from_dict_invalid_state_code(self):
"country": "Australia",
}
# This is invalid because state codes are expected to have a max of 8 characters
self.assertRaises(ValueError, to_python, ad)
address = to_python(ad)
self.assertEqual(address.locality.state.code, 'Somethin')

def test_assignment_from_string(self):
self.test.address = to_python(self.ad1_dict["raw"])
Expand Down
1 change: 1 addition & 0 deletions address/widgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ class AddressWidget(forms.TextInput):
("street_number", "street_number"),
("state", "administrative_area_level_1"),
("state_code", "administrative_area_level_1_short"),
('administrative_area_level_3', 'administrative_area_level_3'),
("formatted", "formatted_address"),
("latitude", "lat"),
("longitude", "lng"),
Expand Down
7 changes: 6 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
[tool.poetry]
name = "django-address"
version = "0.2.5"
version = "0.2.6"
description = "A django application for describing addresses."
authors = ["Luke Hodkinson <[email protected]>"]
packages = [
{ include = "address" },
{ include = "address/*.py" },
{ include = "address/**/*.py" },
]

[tool.poetry.dependencies]
python = ">=3.5"
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

from setuptools import find_packages, setup

version = "0.2.5"
version = "0.2.6"

if sys.argv[-1] == "tag":
print("Tagging the version on github:")
Expand Down