From 4b87e13c6b3e50217bbb21b155324aaea15aaab5 Mon Sep 17 00:00:00 2001 From: skulegirl Date: Fri, 23 Dec 2016 21:42:32 -0500 Subject: [PATCH 01/15] Port to Python 3.5 --- README.rst | 16 +++++++++++++--- setup.py | 2 +- src/postal/forms/__init__.py | 2 +- src/postal/resource.py | 14 +++++++------- 4 files changed, 22 insertions(+), 12 deletions(-) diff --git a/README.rst b/README.rst index 4ea5e79..00f62a0 100644 --- a/README.rst +++ b/README.rst @@ -41,19 +41,29 @@ Dependencies ============ django-countries (http://pypi.python.org/pypi/django-countries) +django-localflavor (http://pypi.python.org/pypi/django-localflavor) Usage ===== -1. Add django-countries and django-postal to your ``INSTALLED_APPS`` in ``settings.py`` +1. Add django-countries, django-localflavor and django-postal to your ``INSTALLED_APPS`` in ``settings.py`` e.g.:: INSTALLED_APPS = ( - "countries", + "django_countries", + "localflavor", "postal", ... ) +2. Include the postal urls in your main ``urls.py`` file:: + + urlpatterns = [ + # ... + url(r'^postal/', include('postal.urls')), + # ... + ] + 3. Add a ``postal_form`` to your templates:: some_template.html @@ -77,7 +87,7 @@ e.g.:: Changing the country in the form above should localise the address form. -3. In your view code add code to save the addressform e.g.:: +4. In your view code add code to save the addressform e.g.:: from postal.forms import PostalAddressForm diff --git a/setup.py b/setup.py index 8299298..ed39817 100644 --- a/setup.py +++ b/setup.py @@ -20,7 +20,7 @@ def read(fname): package_dir={'': 'src'}, package_data={'': ['*.txt', '*.js', '*.html', '*.*', 'templates/postal/*.html']}, - install_requires=['setuptools', 'django-countries'], + install_requires=['setuptools', 'django-countries', 'django-localflavor'], classifiers=[ 'Development Status :: 3 - Alpha', diff --git a/src/postal/forms/__init__.py b/src/postal/forms/__init__.py index 0ac78ab..faa5d06 100644 --- a/src/postal/forms/__init__.py +++ b/src/postal/forms/__init__.py @@ -5,7 +5,7 @@ from postal.settings import POSTAL_ADDRESS_LINE1, POSTAL_ADDRESS_LINE2, POSTAL_ADDRESS_CITY, POSTAL_ADDRESS_STATE, \ POSTAL_ADDRESS_CODE -country_list = [('', '-'*45)] + country_data.COUNTRIES.items() +country_list = [('', '-'*45)] + list(country_data.COUNTRIES.items()) class PostalAddressForm(forms.Form): diff --git a/src/postal/resource.py b/src/postal/resource.py index df1fbfb..ffe1206 100644 --- a/src/postal/resource.py +++ b/src/postal/resource.py @@ -8,7 +8,7 @@ from django.core.urlresolvers import NoReverseMatch from django.db.models import Model, permalink from django.http import HttpResponse, HttpResponseNotAllowed, HttpResponseServerError -from django.utils.encoding import smart_unicode +from django.utils.encoding import smart_text from django.views.debug import ExceptionReporter from django.views.decorators.vary import vary_on_headers from django.conf import settings @@ -66,7 +66,7 @@ def construct(self): """ Recursively serialize a lot of types, and in cases where it doesn't recognize the type, - it will fall back to Django's `smart_unicode`. + it will fall back to Django's `smart_text`. Returns `dict`. """ @@ -98,7 +98,7 @@ def _any(thing, fields=None): elif repr(thing).startswith(" Date: Tue, 27 Dec 2016 23:09:47 -0500 Subject: [PATCH 02/15] More python 3.5 support; support for crispy forms and embedding within another form; add support for CA and AU --- src/postal/api/handlers.py | 4 +-- src/postal/forms/__init__.py | 31 ++++++++++++++-- src/postal/forms/au/__init__.py | 0 src/postal/forms/au/forms.py | 17 +++++++++ src/postal/forms/ca/__init__.py | 0 src/postal/forms/ca/forms.py | 18 ++++++++++ src/postal/library.py | 4 +++ src/postal/resource.py | 14 ++++---- src/postal/settings.py | 4 ++- src/postal/templates/postal/crispyform.html | 2 ++ src/postal/templates/postal/form.html | 4 ++- .../postal/monitor_country_change.html | 6 ++-- src/postal/tests/__init__.py | 2 -- src/postal/tests/test_l10n.py | 3 +- src/postal/utils.py | 30 ++++++++++------ src/postal/views.py | 35 ++++++++++++------- 16 files changed, 133 insertions(+), 41 deletions(-) create mode 100644 src/postal/forms/au/__init__.py create mode 100644 src/postal/forms/au/forms.py create mode 100644 src/postal/forms/ca/__init__.py create mode 100644 src/postal/forms/ca/forms.py create mode 100644 src/postal/templates/postal/crispyform.html diff --git a/src/postal/api/handlers.py b/src/postal/api/handlers.py index d743118..a0425ba 100644 --- a/src/postal/api/handlers.py +++ b/src/postal/api/handlers.py @@ -5,7 +5,7 @@ class PostalHandler(BaseHandler): allowed_methods = ('GET',) - def read(self, request): + def read(self, request): iso_code = request.GET.get('country', '') json = {} form_class = form_factory(country_code=iso_code) @@ -13,6 +13,6 @@ def read(self, request): for k, v in form_obj.fields.items(): if k not in json.keys(): json[k] = {} - json[k]['label'] = unicode(v.label) + json[k]['label'] = str(v.label) json[k]['widget'] = v.widget.render(k, "", attrs={'id': 'id_' + k}) return json diff --git a/src/postal/forms/__init__.py b/src/postal/forms/__init__.py index faa5d06..fb0b072 100644 --- a/src/postal/forms/__init__.py +++ b/src/postal/forms/__init__.py @@ -2,10 +2,15 @@ from django.utils.translation import ugettext_lazy as _ from django_countries import data as country_data + from postal.settings import POSTAL_ADDRESS_LINE1, POSTAL_ADDRESS_LINE2, POSTAL_ADDRESS_CITY, POSTAL_ADDRESS_STATE, \ - POSTAL_ADDRESS_CODE + POSTAL_ADDRESS_CODE, POSTAL_USE_CRISPY_FORMS + +if POSTAL_USE_CRISPY_FORMS: + from crispy_forms.helper import FormHelper + from crispy_forms.layout import Layout, Div -country_list = [('', '-'*45)] + list(country_data.COUNTRIES.items()) +country_list = sorted([('', '-'*45)] + list(country_data.COUNTRIES.items())) class PostalAddressForm(forms.Form): @@ -16,6 +21,28 @@ class PostalAddressForm(forms.Form): code = forms.CharField(label=POSTAL_ADDRESS_CODE[0], required=POSTAL_ADDRESS_CODE[1], max_length=100) country = forms.ChoiceField(label=_(u"Country"), choices=country_list) + def __init__(self, *args, **kwargs): + super(forms.Form, self).__init__(*args, **kwargs) + self.state = '' + if POSTAL_USE_CRISPY_FORMS: + css_id = 'postal_address' + if 'prefix' in kwargs: + css_id = kwargs['prefix'] + '-' + css_id + self.helper = FormHelper() + self.helper.form_tag = False + self.helper.layout = Layout( + Div( + 'line1', + 'line2' + 'city', + 'country', + 'state', + 'code', + css_id=css_id, + css_class='postal_address' + ) + ) + def clean_country(self): data = self.cleaned_data['country'] if data not in country_data.COUNTRIES.keys(): diff --git a/src/postal/forms/au/__init__.py b/src/postal/forms/au/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/postal/forms/au/forms.py b/src/postal/forms/au/forms.py new file mode 100644 index 0000000..7e95215 --- /dev/null +++ b/src/postal/forms/au/forms.py @@ -0,0 +1,17 @@ +""" http://www.bitboost.com/ref/international-address-formats.html """ +from django import forms +from django.utils.translation import ugettext_lazy as _ +from localflavor.au.forms import AUPostCodeField, AUStateSelect + +from postal.forms import PostalAddressForm + +class AUPostalAddressForm(PostalAddressForm): + line1 = forms.CharField(label=_(u"Street"), max_length=50) + line2 = forms.CharField(label=_(u"Area"), required=False, max_length=100) + city = forms.CharField(label=_(u"City"), max_length=50) + state = forms.CharField(label=_(u"US State"), widget=AUStateSelect) + code = AUPostCodeField(label=_(u"Zip Code")) + + def __init__(self, *args, **kwargs): + super(AUPostalAddressForm, self).__init__(*args, **kwargs) + self.fields['country'].initial = "AU" diff --git a/src/postal/forms/ca/__init__.py b/src/postal/forms/ca/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/postal/forms/ca/forms.py b/src/postal/forms/ca/forms.py new file mode 100644 index 0000000..b22d2bf --- /dev/null +++ b/src/postal/forms/ca/forms.py @@ -0,0 +1,18 @@ +""" http://www.bitboost.com/ref/international-address-formats.html """ +from django import forms +from django.utils.translation import ugettext_lazy as _ +from localflavor.ca.forms import CAPostalCodeField, CAProvinceField, CAProvinceSelect + +from postal.forms import PostalAddressForm + + +class CAPostalAddressForm(PostalAddressForm): + line1 = forms.CharField(label=_(u"Street"), max_length=50) + line2 = forms.CharField(label=_(u"Area"), required=False, max_length=100) + city = forms.CharField(label=_(u"City"), max_length=50) + state = CAProvinceField(label=_(u"Province"), widget=CAProvinceSelect) + code = CAPostalCodeField(label=_(u"Postal Code")) + + def __init__(self, *args, **kwargs): + super(CAPostalAddressForm, self).__init__(*args, **kwargs) + self.fields['country'].initial = "CA" diff --git a/src/postal/library.py b/src/postal/library.py index f8f4f23..6501261 100644 --- a/src/postal/library.py +++ b/src/postal/library.py @@ -13,9 +13,12 @@ from postal.forms.pl.forms import PLPostalAddressForm from postal.forms.ru.forms import RUPostalAddressForm from postal.forms.us.forms import USPostalAddressForm +from postal.forms.ca.forms import CAPostalAddressForm +from postal.forms.au.forms import AUPostalAddressForm # TODO: Auto-import these forms country_map = { + "ca": CAPostalAddressForm, "co": COPostalAddressForm, "cz": CZPostalAddressForm, "de": DEPostalAddressForm, @@ -28,6 +31,7 @@ "ru": RUPostalAddressForm, "us": USPostalAddressForm, "ar": ARPostalAddressForm, + "au": AUPostalAddressForm, } diff --git a/src/postal/resource.py b/src/postal/resource.py index ffe1206..0ca36c0 100644 --- a/src/postal/resource.py +++ b/src/postal/resource.py @@ -304,7 +304,7 @@ def get(cls, format): """ Gets an emitter, returns the class and a content-type. """ - if cls.EMITTERS.has_key(format): + if format in cls.EMITTERS: return cls.EMITTERS.get(format) raise ValueError("No emitters found for type %s" % format) @@ -557,15 +557,15 @@ def __call__(self, request, *args, **kwargs): status_code = 200 # If we're looking at a response object which contains non-string - # content, then assume we should use the emitter to format that + # content, then assume we should use the emitter to format that # content if isinstance(result, HttpResponse) and not result._is_string: status_code = result.status_code # Note: We can't use result.content here because that method attempts - # to convert the content into a string which we don't want. + # to convert the content into a string which we don't want. # when _is_string is False _container is the raw data result = result._container - + srl = emitter(result, typemapper, handler, fields, anonymous) try: @@ -575,8 +575,10 @@ def __call__(self, request, *args, **kwargs): before sending it to the client. Won't matter for smaller datasets, but larger will have an impact. """ - if self.stream: stream = srl.stream_render(request) - else: stream = srl.render(request) + if self.stream: + stream = srl.stream_render(request) + else: + stream = srl.render(request) if not isinstance(stream, HttpResponse): resp = HttpResponse(stream, mimetype=ct, status=status_code) diff --git a/src/postal/settings.py b/src/postal/settings.py index 1d6f1a2..fd3ac09 100644 --- a/src/postal/settings.py +++ b/src/postal/settings.py @@ -2,10 +2,12 @@ from django.utils.translation import ugettext_lazy as _ POSTAL_ADDRESS_L10N = getattr(settings, 'POSTAL_ADDRESS_L10N', True) +POSTAL_USE_CRISPY_FORMS = getattr(settings, 'POSTAL_USE_CRISPY_FORMS', False) # each address line is a tuple of format (field_label, required) POSTAL_ADDRESS_LINE1 = getattr(settings, "POSTAL_ADDRESS_LINE1", (_(u"Street"), False)) POSTAL_ADDRESS_LINE2 = getattr(settings, "POSTAL_ADDRESS_LINE2", (_(u"Area"), False)) POSTAL_ADDRESS_CITY = getattr(settings, "POSTAL_ADDRESS_CITY", (_(u"City"), False)) POSTAL_ADDRESS_STATE = getattr(settings, "POSTAL_ADDRESS_STATE", (_(u"State"), False)) -POSTAL_ADDRESS_CODE = getattr(settings, "POSTAL_ADDRESS_CODE", (_(u"Zip code"), False)) \ No newline at end of file +POSTAL_ADDRESS_CODE = getattr(settings, "POSTAL_ADDRESS_CODE", (_(u"Zip code"), False)) + diff --git a/src/postal/templates/postal/crispyform.html b/src/postal/templates/postal/crispyform.html new file mode 100644 index 0000000..96b515a --- /dev/null +++ b/src/postal/templates/postal/crispyform.html @@ -0,0 +1,2 @@ +{% load crispy_forms_tags %} +{% crispy form %} \ No newline at end of file diff --git a/src/postal/templates/postal/form.html b/src/postal/templates/postal/form.html index 07ad81f..5cf86b7 100644 --- a/src/postal/templates/postal/form.html +++ b/src/postal/templates/postal/form.html @@ -1 +1,3 @@ -{{form.as_p}} \ No newline at end of file +
+{{form.as_p}} +
\ No newline at end of file diff --git a/src/postal/templates/postal/monitor_country_change.html b/src/postal/templates/postal/monitor_country_change.html index e9720ca..541dec8 100644 --- a/src/postal/templates/postal/monitor_country_change.html +++ b/src/postal/templates/postal/monitor_country_change.html @@ -7,7 +7,7 @@ data: $(form).serialize(), success: function(response) { var data = JSON.parse(response); - holder.html(data['postal_address'] + "{%csrf_token%}"); + $(holder).replaceWith(data['postal_address']); }, error: function(response) { alert(response); @@ -16,8 +16,8 @@ } $.fn.monitor_country_change = function(country_selector){ - var holder = this; - $(country_selector).live('change', function() { + $('body').on('change', country_selector, function() { + var holder = $(this).closest('div.postal_address'); var form = $(this).closest('form'); change_form(form, holder); }); diff --git a/src/postal/tests/__init__.py b/src/postal/tests/__init__.py index fe9624b..e69de29 100644 --- a/src/postal/tests/__init__.py +++ b/src/postal/tests/__init__.py @@ -1,2 +0,0 @@ -from test_l10n import * -from test_widgets import * \ No newline at end of file diff --git a/src/postal/tests/test_l10n.py b/src/postal/tests/test_l10n.py index 4c23dc9..65b411e 100644 --- a/src/postal/tests/test_l10n.py +++ b/src/postal/tests/test_l10n.py @@ -1,6 +1,7 @@ from django.test import TestCase from django.utils.translation import ugettext from django import forms +from importlib import reload from postal.library import form_factory import postal.settings @@ -46,7 +47,7 @@ def test_get_de_address(self): form = german_form_class(data=test_data) self.assertEqual(form.fields['line1'].label.lower(), "street") - self.assertEqual(form.fields.has_key('line2'), False) + self.assertEqual(('line2' in form.fields), False) self.assertEqual(form.fields['city'].label.lower(), "city") self.assertEqual(form.fields['code'].label.lower(), "zip code") diff --git a/src/postal/utils.py b/src/postal/utils.py index e1f26f4..997be18 100644 --- a/src/postal/utils.py +++ b/src/postal/utils.py @@ -28,7 +28,7 @@ class RcFactory(object): def __getattr__(self, attr): """ - Returns a fresh `HttpResponse` when getting + Returns a fresh `HttpResponse` when getting an "attribute". This is backwards compatible with 0.2, which is important. """ @@ -39,29 +39,39 @@ def __getattr__(self, attr): class HttpResponseWrapper(HttpResponse): """ - Wrap HttpResponse and make sure that the internal _is_string - flag is updated when the _set_content method (via the content + Wrap HttpResponse and make sure that the internal _is_string + flag is updated when the _set_content method (via the content property) is called """ + def _set_content(self, content): """ - Set the _container and _is_string properties based on the + Set the _container and _is_string properties based on the type of the value parameter. This logic is in the construtor - for HttpResponse, but doesn't get repeated when setting + for HttpResponse, but doesn't get repeated when setting HttpResponse.content although this bug report (feature request) - suggests that it should: http://code.djangoproject.com/ticket/9403 + suggests that it should: http://code.djangoproject.com/ticket/9403 """ - if not isinstance(content, basestring) and hasattr(content, '__iter__'): + if not isinstance(content, str) and hasattr(content, '__iter__'): self._container = content self._is_string = False else: - self._container = [content] + self._container = [str.encode(content)] self._is_string = True - content = property(HttpResponse._get_content, _set_content) + try: + # Django version is older than 1.5 + content = property(HttpResponse._get_content, _set_content) + except: + # Django version 1.5 or greater + @HttpResponse.content.setter + def content(self, content): + print("Setting conttent to %s" % content) + self._set_content(content) return HttpResponseWrapper(r, content_type='text/plain', status=c) - + + rc = RcFactory() diff --git a/src/postal/views.py b/src/postal/views.py index be19577..2f8c120 100644 --- a/src/postal/views.py +++ b/src/postal/views.py @@ -6,39 +6,48 @@ except ImportError: import json as simplejson from postal.library import form_factory +from postal.settings import POSTAL_USE_CRISPY_FORMS def address_inline(request, prefix="", country_code=None, template_name="postal/form.html"): """ Displays postal address with localized fields """ - country_prefix = "country" prefix = request.POST.get('prefix', prefix) - + if prefix: country_prefix = prefix + '-country' - country_code = request.POST.get(country_prefix, country_code) + form_class = form_factory(country_code=country_code) - + if request.method == "POST": data = {} for (key, val) in request.POST.items(): if val is not None and len(val) > 0: data[key] = val data.update({country_prefix: country_code}) - + form = form_class(prefix=prefix, initial=data) else: form = form_class(prefix=prefix) - - return render_to_string(template_name, RequestContext(request, { - "form": form, - "prefix": prefix, - })) + + return render_to_string( + template_name, + context={ + "form": form, + "prefix": prefix, + }, + request=request + ) def changed_country(request): - result = simplejson.dumps({ - "postal_address": address_inline(request), - }) + if POSTAL_USE_CRISPY_FORMS: + result = simplejson.dumps({ + "postal_address": address_inline(request, template_name="postal/crispyform.html") + }) + else: + result = simplejson.dumps({ + "postal_address": address_inline(request), + }) return HttpResponse(result) \ No newline at end of file From 791cb153e981ebd7822c99d46c092fe4cb5cb05c Mon Sep 17 00:00:00 2001 From: skulegirl Date: Wed, 28 Dec 2016 21:00:44 -0500 Subject: [PATCH 03/15] Remove error trying to reset state --- src/postal/forms/__init__.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/postal/forms/__init__.py b/src/postal/forms/__init__.py index fb0b072..d47e4ba 100644 --- a/src/postal/forms/__init__.py +++ b/src/postal/forms/__init__.py @@ -23,7 +23,6 @@ class PostalAddressForm(forms.Form): def __init__(self, *args, **kwargs): super(forms.Form, self).__init__(*args, **kwargs) - self.state = '' if POSTAL_USE_CRISPY_FORMS: css_id = 'postal_address' if 'prefix' in kwargs: From c5189407e3f1a74a0fbd0b4032e61051903cf107 Mon Sep 17 00:00:00 2001 From: skulegirl Date: Wed, 28 Dec 2016 23:16:07 -0500 Subject: [PATCH 04/15] Fix missing comma in PostalAddressForm layout; remove Required=False from NL fields that should be required; change line2 description in other country forms. --- src/postal/forms/__init__.py | 4 ++-- src/postal/forms/au/forms.py | 2 +- src/postal/forms/ca/forms.py | 2 +- src/postal/forms/nl/forms.py | 4 ++-- src/postal/forms/us/forms.py | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/postal/forms/__init__.py b/src/postal/forms/__init__.py index d47e4ba..7227902 100644 --- a/src/postal/forms/__init__.py +++ b/src/postal/forms/__init__.py @@ -32,8 +32,8 @@ def __init__(self, *args, **kwargs): self.helper.layout = Layout( Div( 'line1', - 'line2' - 'city', + 'line2', + 'city', 'country', 'state', 'code', diff --git a/src/postal/forms/au/forms.py b/src/postal/forms/au/forms.py index 7e95215..c3aca28 100644 --- a/src/postal/forms/au/forms.py +++ b/src/postal/forms/au/forms.py @@ -7,7 +7,7 @@ class AUPostalAddressForm(PostalAddressForm): line1 = forms.CharField(label=_(u"Street"), max_length=50) - line2 = forms.CharField(label=_(u"Area"), required=False, max_length=100) + line2 = forms.CharField(label=_(u"Street (con\'t)"), required=False, max_length=100) city = forms.CharField(label=_(u"City"), max_length=50) state = forms.CharField(label=_(u"US State"), widget=AUStateSelect) code = AUPostCodeField(label=_(u"Zip Code")) diff --git a/src/postal/forms/ca/forms.py b/src/postal/forms/ca/forms.py index b22d2bf..d8797d6 100644 --- a/src/postal/forms/ca/forms.py +++ b/src/postal/forms/ca/forms.py @@ -8,7 +8,7 @@ class CAPostalAddressForm(PostalAddressForm): line1 = forms.CharField(label=_(u"Street"), max_length=50) - line2 = forms.CharField(label=_(u"Area"), required=False, max_length=100) + line2 = forms.CharField(label=_(u"Street (con\'t)"), required=False, max_length=100) city = forms.CharField(label=_(u"City"), max_length=50) state = CAProvinceField(label=_(u"Province"), widget=CAProvinceSelect) code = CAPostalCodeField(label=_(u"Postal Code")) diff --git a/src/postal/forms/nl/forms.py b/src/postal/forms/nl/forms.py index 28d43e8..74c31f7 100644 --- a/src/postal/forms/nl/forms.py +++ b/src/postal/forms/nl/forms.py @@ -5,9 +5,9 @@ from postal.forms import PostalAddressForm class NLPostalAddressForm(PostalAddressForm): - line1 = forms.CharField(label=_(u"Street"), required=False, max_length=100) + line1 = forms.CharField(label=_(u"Street"), max_length=100) line2 = forms.CharField(label=_(u"Area"), required=False, max_length=100) - city = forms.CharField(label=_(u"Town/City"), required=False, max_length=100) + city = forms.CharField(label=_(u"Town/City"), max_length=100) code = NLZipCodeField(label=_(u"Zip Code")) diff --git a/src/postal/forms/us/forms.py b/src/postal/forms/us/forms.py index 8986c2e..3a63ec6 100644 --- a/src/postal/forms/us/forms.py +++ b/src/postal/forms/us/forms.py @@ -7,7 +7,7 @@ class USPostalAddressForm(PostalAddressForm): line1 = forms.CharField(label=_(u"Street"), max_length=50) - line2 = forms.CharField(label=_(u"Area"), required=False, max_length=100) + line2 = forms.CharField(label=_(u"Street (con\'t)"), required=False, max_length=100) city = forms.CharField(label=_(u"City"), max_length=50) state = USStateField(label=_(u"US State"), widget=USStateSelect) code = USZipCodeField(label=_(u"Zip Code")) From 98d82c793df3506b786a3c55f5dae6b98b48f39a Mon Sep 17 00:00:00 2001 From: skulegirl Date: Tue, 3 Jan 2017 22:19:52 -0500 Subject: [PATCH 05/15] Move country to top of postal address form so tabbing works correctly --- src/postal/forms/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/postal/forms/__init__.py b/src/postal/forms/__init__.py index 7227902..9652bf0 100644 --- a/src/postal/forms/__init__.py +++ b/src/postal/forms/__init__.py @@ -31,10 +31,10 @@ def __init__(self, *args, **kwargs): self.helper.form_tag = False self.helper.layout = Layout( Div( + 'country', 'line1', 'line2', 'city', - 'country', 'state', 'code', css_id=css_id, From 154677fed1b17b63ff14db2aa0f9a8f4033e3d08 Mon Sep 17 00:00:00 2001 From: skulegirl Date: Tue, 10 Jan 2017 12:00:39 -0500 Subject: [PATCH 06/15] Change NL zip code encoding to remove space --- src/postal/forms/nl/forms.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/postal/forms/nl/forms.py b/src/postal/forms/nl/forms.py index 74c31f7..951bc28 100644 --- a/src/postal/forms/nl/forms.py +++ b/src/postal/forms/nl/forms.py @@ -1,14 +1,25 @@ from django import forms from django.utils.translation import ugettext_lazy as _ +from django.utils import six from localflavor.nl.forms import NLZipCodeField from postal.forms import PostalAddressForm +class MyNLZipCodeField(NLZipCodeField): + def clean(self, value): + if isinstance(value, six.string_types): + value = value.upper().replace(' ', '') + + # don't strip the spaces out of the zipcode, it confuses + # the geocoders + return super(NLZipCodeField, self).clean(value) + + class NLPostalAddressForm(PostalAddressForm): line1 = forms.CharField(label=_(u"Street"), max_length=100) line2 = forms.CharField(label=_(u"Area"), required=False, max_length=100) city = forms.CharField(label=_(u"Town/City"), max_length=100) - code = NLZipCodeField(label=_(u"Zip Code")) + code = MyNLZipCodeField(label=_(u"Zip Code")) class Meta: From 5e2d084a7b53e3156f4ea4465396b22a5e4e7fd5 Mon Sep 17 00:00:00 2001 From: Anna Maste Date: Fri, 31 Mar 2017 11:46:00 -0400 Subject: [PATCH 07/15] Fix redisplay of address form after country change when using crispy layout - need to register the form helper now. --- src/postal/forms/__init__.py | 28 ++++++++++++++++++++-------- src/postal/library.py | 1 - src/postal/views.py | 5 +++-- 3 files changed, 23 insertions(+), 11 deletions(-) diff --git a/src/postal/forms/__init__.py b/src/postal/forms/__init__.py index 9652bf0..a4f4489 100644 --- a/src/postal/forms/__init__.py +++ b/src/postal/forms/__init__.py @@ -8,9 +8,15 @@ if POSTAL_USE_CRISPY_FORMS: from crispy_forms.helper import FormHelper - from crispy_forms.layout import Layout, Div + from crispy_forms.layout import Layout, Div, Hidden -country_list = sorted([('', '-'*45)] + list(country_data.COUNTRIES.items())) +country_list = sorted([('', '-' * 45)] + list(country_data.COUNTRIES.items())) + +form_helpers = {} + + +def register_postal_form_helper(form_id, form_helper): + form_helpers[form_id] = form_helper class PostalAddressForm(forms.Form): @@ -22,25 +28,31 @@ class PostalAddressForm(forms.Form): country = forms.ChoiceField(label=_(u"Country"), choices=country_list) def __init__(self, *args, **kwargs): - super(forms.Form, self).__init__(*args, **kwargs) + prefix = kwargs.pop('prefix', None) + postal_form_id = kwargs.pop('postal_form_id', 'postal-address-form') if POSTAL_USE_CRISPY_FORMS: css_id = 'postal_address' - if 'prefix' in kwargs: - css_id = kwargs['prefix'] + '-' + css_id - self.helper = FormHelper() + if prefix is not None: + css_id = prefix + '-' + css_id + if postal_form_id in form_helpers: + self.helper = form_helpers[postal_form_id] + else: + self.helper = FormHelper() self.helper.form_tag = False self.helper.layout = Layout( Div( 'country', 'line1', 'line2', - 'city', + 'city', 'state', 'code', css_id=css_id, css_class='postal_address' - ) + ), + Hidden('postal-form-id', postal_form_id), ) + super(PostalAddressForm, self).__init__(*args, **kwargs) def clean_country(self): data = self.cleaned_data['country'] diff --git a/src/postal/library.py b/src/postal/library.py index 6501261..3996755 100644 --- a/src/postal/library.py +++ b/src/postal/library.py @@ -1,4 +1,3 @@ -from django import forms from postal import settings as postal_settings from postal.forms import PostalAddressForm from postal.forms.ar.forms import ARPostalAddressForm diff --git a/src/postal/views.py b/src/postal/views.py index 2f8c120..2546489 100644 --- a/src/postal/views.py +++ b/src/postal/views.py @@ -17,6 +17,7 @@ def address_inline(request, prefix="", country_code=None, template_name="postal/ if prefix: country_prefix = prefix + '-country' country_code = request.POST.get(country_prefix, country_code) + postal_form_id = request.POST.get('postal-form-id', 'postal-address-form') form_class = form_factory(country_code=country_code) @@ -27,9 +28,9 @@ def address_inline(request, prefix="", country_code=None, template_name="postal/ data[key] = val data.update({country_prefix: country_code}) - form = form_class(prefix=prefix, initial=data) + form = form_class(prefix=prefix, initial=data, postal_form_id=postal_form_id) else: - form = form_class(prefix=prefix) + form = form_class(prefix=prefix, postal_form_id=postal_form_id) return render_to_string( template_name, From 143356f0678756dc6ca0406003180c1800da9bed Mon Sep 17 00:00:00 2001 From: Anna Maste Date: Fri, 9 Jun 2017 23:09:13 -0400 Subject: [PATCH 08/15] Fix sorting of countries to be by name not by code --- src/postal/forms/__init__.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/postal/forms/__init__.py b/src/postal/forms/__init__.py index a4f4489..6db4058 100644 --- a/src/postal/forms/__init__.py +++ b/src/postal/forms/__init__.py @@ -10,7 +10,12 @@ from crispy_forms.helper import FormHelper from crispy_forms.layout import Layout, Div, Hidden -country_list = sorted([('', '-' * 45)] + list(country_data.COUNTRIES.items())) + +def country_sort_key(country_data): + return country_data[1] + + +country_list = sorted([('', '-' * 45)] + list(country_data.COUNTRIES.items()), key=country_sort_key) form_helpers = {} From aabd9bb3ac733bb61fa665619baafa13239355c3 Mon Sep 17 00:00:00 2001 From: Anna Maste Date: Fri, 6 Oct 2017 12:01:15 -0400 Subject: [PATCH 09/15] Put US and Canada first in country lists --- src/postal/forms/__init__.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/postal/forms/__init__.py b/src/postal/forms/__init__.py index 6db4058..b1e737b 100644 --- a/src/postal/forms/__init__.py +++ b/src/postal/forms/__init__.py @@ -12,6 +12,10 @@ def country_sort_key(country_data): + if country_data[0] == 'US': + return 'AAA' + if country_data[0] == 'CA': + return 'AAAA' return country_data[1] From e0ed55cde3914bcf83ff51478bd5452f6e752f7e Mon Sep 17 00:00:00 2001 From: Anna Maste Date: Sun, 18 Nov 2018 09:54:14 -0500 Subject: [PATCH 10/15] Update text on street in form --- src/postal/forms/ca/forms.py | 4 ++-- src/postal/forms/us/forms.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/postal/forms/ca/forms.py b/src/postal/forms/ca/forms.py index d8797d6..6dca1db 100644 --- a/src/postal/forms/ca/forms.py +++ b/src/postal/forms/ca/forms.py @@ -7,8 +7,8 @@ class CAPostalAddressForm(PostalAddressForm): - line1 = forms.CharField(label=_(u"Street"), max_length=50) - line2 = forms.CharField(label=_(u"Street (con\'t)"), required=False, max_length=100) + line1 = forms.CharField(label=_(u"Street Address"), max_length=50) + line2 = forms.CharField(label=_(u"Street Address (con\'t)"), required=False, max_length=100) city = forms.CharField(label=_(u"City"), max_length=50) state = CAProvinceField(label=_(u"Province"), widget=CAProvinceSelect) code = CAPostalCodeField(label=_(u"Postal Code")) diff --git a/src/postal/forms/us/forms.py b/src/postal/forms/us/forms.py index 3a63ec6..b546ebf 100644 --- a/src/postal/forms/us/forms.py +++ b/src/postal/forms/us/forms.py @@ -6,8 +6,8 @@ from postal.forms import PostalAddressForm class USPostalAddressForm(PostalAddressForm): - line1 = forms.CharField(label=_(u"Street"), max_length=50) - line2 = forms.CharField(label=_(u"Street (con\'t)"), required=False, max_length=100) + line1 = forms.CharField(label=_(u"Street Address"), max_length=50) + line2 = forms.CharField(label=_(u"Street Address (con\'t)"), required=False, max_length=100) city = forms.CharField(label=_(u"City"), max_length=50) state = USStateField(label=_(u"US State"), widget=USStateSelect) code = USZipCodeField(label=_(u"Zip Code")) From 7a84589661beac98a4c91b33d46c3235a496d400 Mon Sep 17 00:00:00 2001 From: Anna Maste Date: Thu, 15 Aug 2019 11:28:35 -0400 Subject: [PATCH 11/15] Reload province selection on history navigation --- .../templates/postal/monitor_country_change.html | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/postal/templates/postal/monitor_country_change.html b/src/postal/templates/postal/monitor_country_change.html index 541dec8..52a7f06 100644 --- a/src/postal/templates/postal/monitor_country_change.html +++ b/src/postal/templates/postal/monitor_country_change.html @@ -21,6 +21,17 @@ var form = $(this).closest('form'); change_form(form, holder); }); + + window.addEventListener( "pageshow", function ( event ) { + var historyTraversal = event.persisted || + ( typeof window.performance != "undefined" && + window.performance.navigation.type === 2 ); + if ( historyTraversal ) { + var holder = $(country_selector).closest('div.postal_address'); + var form = $(country_selector).closest('form'); + change_form(form, holder); + } + }); } })(jQuery); \ No newline at end of file From fb306480f482e169dcacdec3297de4246ddff009 Mon Sep 17 00:00:00 2001 From: Suyash Unnithan Date: Mon, 16 Mar 2020 11:10:28 -0400 Subject: [PATCH 12/15] django 2.0.13 --- src/postal/resource.py | 2 +- src/postal/templatetags/postal_tags.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/postal/resource.py b/src/postal/resource.py index 0ca36c0..6bcb539 100644 --- a/src/postal/resource.py +++ b/src/postal/resource.py @@ -5,7 +5,7 @@ import inspect import re import sys -from django.core.urlresolvers import NoReverseMatch +from django.urls import NoReverseMatch from django.db.models import Model, permalink from django.http import HttpResponse, HttpResponseNotAllowed, HttpResponseServerError from django.utils.encoding import smart_text diff --git a/src/postal/templatetags/postal_tags.py b/src/postal/templatetags/postal_tags.py index b9d9d0b..d3e751a 100644 --- a/src/postal/templatetags/postal_tags.py +++ b/src/postal/templatetags/postal_tags.py @@ -1,5 +1,5 @@ from django import template -from django.core.urlresolvers import reverse +from django.urls import reverse register = template.Library() From a16ae9ca9dca824e464f4513238a2aa2bf5c4e5e Mon Sep 17 00:00:00 2001 From: Suyash Unnithan Date: Wed, 18 Mar 2020 19:13:13 -0400 Subject: [PATCH 13/15] django 2.1.15 fix --- src/postal/resource.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/postal/resource.py b/src/postal/resource.py index 6bcb539..d6eeac8 100644 --- a/src/postal/resource.py +++ b/src/postal/resource.py @@ -5,8 +5,8 @@ import inspect import re import sys -from django.urls import NoReverseMatch -from django.db.models import Model, permalink +from django.urls import NoReverseMatch, reverse +from django.db.models import Model from django.http import HttpResponse, HttpResponseNotAllowed, HttpResponseServerError from django.utils.encoding import smart_text from django.views.debug import ExceptionReporter @@ -238,7 +238,7 @@ def _model(data, fields=None): url_id, fields = handler.resource_uri(data) try: - ret['resource_uri'] = permalink(lambda: (url_id, fields))() + ret['resource_uri'] = reverse(lambda: (url_id, fields))() except NoReverseMatch as e: pass From aca16b515d1f215229ce68b7cf7fd211bea16bab Mon Sep 17 00:00:00 2001 From: Suyash Unnithan Date: Thu, 19 Mar 2020 14:50:14 -0400 Subject: [PATCH 14/15] django_2.1.15 fix --- src/postal/resource.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/postal/resource.py b/src/postal/resource.py index d6eeac8..7b8e6f4 100644 --- a/src/postal/resource.py +++ b/src/postal/resource.py @@ -238,7 +238,7 @@ def _model(data, fields=None): url_id, fields = handler.resource_uri(data) try: - ret['resource_uri'] = reverse(lambda: (url_id, fields))() + ret['resource_uri'] = reverse(url_id, fields) except NoReverseMatch as e: pass From beb52948f315a67bc68cba909938e9c61276e542 Mon Sep 17 00:00:00 2001 From: skulegirl Date: Thu, 19 Mar 2020 15:26:02 -0400 Subject: [PATCH 15/15] Add args= to reverse call --- src/postal/resource.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/postal/resource.py b/src/postal/resource.py index 7b8e6f4..91deecd 100644 --- a/src/postal/resource.py +++ b/src/postal/resource.py @@ -238,7 +238,7 @@ def _model(data, fields=None): url_id, fields = handler.resource_uri(data) try: - ret['resource_uri'] = reverse(url_id, fields) + ret['resource_uri'] = reverse(url_id, args=fields) except NoReverseMatch as e: pass