This repository has been archived by the owner on Aug 18, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathfields.py
65 lines (50 loc) · 1.93 KB
/
fields.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
import json
from os import path
from django import forms
from django.core.exceptions import ValidationError
from .widgets import AddressWidget
basepath = path.dirname(__file__)
filepath = path.abspath(path.join(basepath, "static", "addressfield.min.json"))
with open(filepath, encoding='utf8') as address_data:
countries = json.load(address_data)['options']
VALIDATION_DATA = {country['iso']: country for country in countries}
ADDRESS_FIELDS_ORDER = [
'thoroughfare', 'premise', 'localityname', 'administrativearea', 'postalcode', 'country'
]
def flatten_data(data):
flattened = dict()
for d in data:
for k, v in d.items():
if isinstance(v, list):
value = flatten_data(v)
else:
value = {k: v}
flattened.update(value)
return flattened
class AddressField(forms.CharField):
"""
The field stores the address in a flattened form,
so the locality components are on the same level as country or premise
"""
widget = AddressWidget
data = VALIDATION_DATA
def clean(self, value, **kwargs):
country = value['country']
try:
country_data = self.data[country]
except KeyError:
raise ValidationError('Invalid country selected')
fields = flatten_data(country_data['fields'])
missing_fields = set(country_data['required']) - set(field for field, value in value.items() if value)
if missing_fields:
missing_field_name = [fields[field]['label'] for field in missing_fields]
raise ValidationError('Please provide data for: {}'.format(', '.join(missing_field_name)))
return super().clean(value, **kwargs)
def to_python(self, value):
return json.dumps(value)
def prepare_value(self, value):
try:
# Handle empty value with "or".
return json.loads(value or {})
except TypeError:
return value