From 78d852a6595d0e45def2da43d498249e39d24982 Mon Sep 17 00:00:00 2001
From: Todd Dembrey <todd.dembrey@torchbox.com>
Date: Thu, 1 Feb 2018 10:40:23 +0000
Subject: [PATCH] Implement a AddressField to incorporate backend clean methods

---
 addressfield/fields.py         | 47 ++++++++++++++++++++++++++++++++++
 opentech/apply/funds/blocks.py |  5 ++--
 2 files changed, 50 insertions(+), 2 deletions(-)
 create mode 100644 addressfield/fields.py

diff --git a/addressfield/fields.py b/addressfield/fields.py
new file mode 100644
index 000000000..1420c2529
--- /dev/null
+++ b/addressfield/fields.py
@@ -0,0 +1,47 @@
+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}
+
+
+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):
+    widget = AddressWidget
+
+    def clean(self, value, **kwargs):
+        country = value['country']
+        try:
+            country_data = VALIDATION_DATA[country]
+        except KeyError:
+            raise ValidationError('Invalid country selected')
+
+        fields = flatten_data(country_data['fields'])
+
+        missing_fields = set(country_data['required']) - set(value.keys())
+        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)))
+
+        super().clean(value, **kwargs)
diff --git a/opentech/apply/funds/blocks.py b/opentech/apply/funds/blocks.py
index 981717d57..11b0fc31d 100644
--- a/opentech/apply/funds/blocks.py
+++ b/opentech/apply/funds/blocks.py
@@ -16,7 +16,7 @@ from opentech.apply.stream_forms.blocks import (
     TextFieldBlock,
 )
 from opentech.apply.categories.blocks import CategoryQuestionBlock
-from addressfield.widgets import AddressWidget
+from addressfield.fields import AddressField
 
 
 def find_duplicates(items):
@@ -165,7 +165,8 @@ class EmailBlock(MustIncludeFieldBlock):
 class AddressFieldBlock(MustIncludeFieldBlock):
     name = 'address'
     description = 'The postal address of the user'
-    widget = AddressWidget
+
+    field_class = AddressField
 
     class Meta:
         label = _('Address')
-- 
GitLab