prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <issue>
  Postcode / Zipcode error message at School creation is misleading
  Since most web browsers autocomplete the postcode in the class creation form as the email address, teachers receive a badly worded AND badly positioned error message (the message makes it sound like the error is in the name)
  It should mention something like, please input a valid postcode / zipcode 
  and be below the postcode field.
  
  </issue>
  <code>
  [start of portal/forms/organisation.py]
  1 # -*- coding: utf-8 -*-
  2 # Code for Life
  3 #
  4 # Copyright (C) 2017, Ocado Innovation Limited
  5 #
  6 # This program is free software: you can redistribute it and/or modify
  7 # it under the terms of the GNU Affero General Public License as
  8 # published by the Free Software Foundation, either version 3 of the
  9 # License, or (at your option) any later version.
  10 #
  11 # This program is distributed in the hope that it will be useful,
  12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14 # GNU Affero General Public License for more details.
  15 #
  16 # You should have received a copy of the GNU Affero General Public License
  17 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
  18 #
  19 # ADDITIONAL TERMS – Section 7 GNU General Public Licence
  20 #
  21 # This licence does not grant any right, title or interest in any “Ocado” logos,
  22 # trade names or the trademark “Ocado” or any other trademarks or domain names
  23 # owned by Ocado Innovation Limited or the Ocado group of companies or any other
  24 # distinctive brand features of “Ocado” as may be secured from time to time. You
  25 # must not distribute any modification of this program using the trademark
  26 # “Ocado” or claim any affiliation or association with Ocado or its employees.
  27 #
  28 # You are not authorised to use the name Ocado (or any of its trade names) or
  29 # the names of any author or contributor in advertising or for publicity purposes
  30 # pertaining to the distribution of this program, without the prior written
  31 # authorisation of Ocado.
  32 #
  33 # Any propagation, distribution or conveyance of this program must include this
  34 # copyright notice and these terms. You must not misrepresent the origins of this
  35 # program; modified versions of the program must be marked as such and not
  36 # identified as the original program.
  37 from django import forms
  38 
  39 from portal.models import School
  40 
  41 from django_countries.widgets import CountrySelectWidget
  42 from  django.core.exceptions import ObjectDoesNotExist
  43 
  44 
  45 class OrganisationForm(forms.ModelForm):
  46 
  47     current_password = forms.CharField(
  48         label='Enter your password',
  49         widget=forms.PasswordInput(attrs={'autocomplete': "off"}))
  50 
  51     class Meta:
  52         model = School
  53         fields = ['name', 'postcode', 'country']
  54         labels = {
  55             'name' : "Name of your school or club",
  56             'postcode' : 'Postcode',
  57             'country' : 'Country',
  58             }
  59         widgets = {
  60             'name' : forms.TextInput(attrs={'autocomplete': "off", 'placeholder': 'Name of your school or club'}),
  61             'postcode' : forms.TextInput(attrs={'autocomplete': "off", 'placeholder': 'Postcode'}),
  62             'country' : CountrySelectWidget(attrs={'class': 'wide'}),
  63             }
  64 
  65     def __init__(self, *args, **kwargs):
  66         self.user = kwargs.pop('user', None)
  67         self.current_school = kwargs.pop('current_school', None)
  68         super(OrganisationForm, self).__init__(*args, **kwargs)
  69         if self.current_school:
  70             del self.fields['current_password']
  71 
  72     def clean(self):
  73         name = self.cleaned_data.get('name', None)
  74         postcode = self.cleaned_data.get('postcode', None)
  75 
  76         if name and postcode:
  77             try:
  78                 school = School.objects.get(name=name, postcode=postcode)
  79             except ObjectDoesNotExist:
  80                 return self.cleaned_data
  81 
  82             if not self.current_school or self.current_school.id != school.id:
  83                 raise forms.ValidationError(
  84                     "There is already a school or club registered with that name and postcode")
  85 
  86         return self.cleaned_data
  87 
  88     def clean_postcode(self):
  89         postcode = self.cleaned_data.get('postcode', None)
  90 
  91         if postcode:
  92             # Basic postcode check for now
  93             if not len(postcode.replace(' ', '')) > 0:
  94                 raise forms.ValidationError("That postcode was not recognised")
  95 
  96         return postcode
  97 
  98     def clean_current_password(self):
  99         current_password = self.cleaned_data.get('current_password', None)
  100         if not self.user.check_password(current_password):
  101             raise forms.ValidationError("Your password was incorrect")
  102 
  103 
  104 class OrganisationJoinForm(forms.Form):
  105     fuzzy_name = forms.CharField(
  106         label="Search for school or club by name or postcode",
  107         widget=forms.TextInput(
  108             attrs={'placeholder': "Enrico Fermi High School"}))
  109 
  110     # Note: the reason this is a CharField rather than a ChoiceField is to avoid having to
  111     # provide choices which was problematic given that the options are dynamically generated.
  112     chosen_org = forms.CharField(
  113         label='Select school or club',
  114         widget=forms.Select(attrs={'class': 'wide'}))
  115 
  116     def clean_chosen_org(self):
  117         chosen_org = self.cleaned_data.get('chosen_org', None)
  118 
  119         if chosen_org and not School.objects.filter(id=int(chosen_org)).exists():
  120             raise forms.ValidationError("That school or club was not recognised")
  121 
  122         return chosen_org
  123 
  124
  [end of portal/forms/organisation.py]
  </code>
  
  I need you to solve this issue by generating a single patch file that I can apply directly to this repository using git apply. Please respond with a single patch file in the following format.
  <patch>
  diff --git a/file.py b/file.py
  --- a/file.py
  +++ b/file.py
  @@ -1,27 +1,35 @@
   def euclidean(a, b):
  -    while b:
  -        a, b = b, a % b
  -    return a
  +    if b == 0:
  +        return a
  +    return euclidean(b, a % b)
   
   
   def bresenham(x0, y0, x1, y1):
       points = []
       dx = abs(x1 - x0)
       dy = abs(y1 - y0)
  -    sx = 1 if x0 < x1 else -1
  -    sy = 1 if y0 < y1 else -1
  -    err = dx - dy
  +    x, y = x0, y0
  +    sx = -1 if x0 > x1 else 1
  +    sy = -1 if y0 > y1 else 1
   
  -    while True:
  -        points.append((x0, y0))
  -        if x0 == x1 and y0 == y1:
  -            break
  -        e2 = 2 * err
  -        if e2 > -dy:
  -            err -= dy
  -            x0 += sx
  -        if e2 < dx:
  -            err += dx
  -            y0 += sy
  +    if dx > dy:
  +        err = dx / 2.0
  +        while x != x1:
  +            points.append((x, y))
  +            err -= dy
  +            if err < 0:
  +                y += sy
  +                err += dx
  +            x += sx
  +    else:
  +        err = dy / 2.0
  +        while y != y1:
  +            points.append((x, y))
  +            err -= dx
  +            if err < 0:
  +                x += sx
  +                err += dy
  +            y += sy
  +
  +    points.append((x, y))
       return points
  
  </patch>
golden_diff: diff --git a/portal/forms/organisation.py b/portal/forms/organisation.py
  --- a/portal/forms/organisation.py
  +++ b/portal/forms/organisation.py
  @@ -52,14 +52,14 @@
           model = School
           fields = ['name', 'postcode', 'country']
           labels = {
  -            'name' : "Name of your school or club",
  -            'postcode' : 'Postcode',
  -            'country' : 'Country',
  +            'name': "Name of your school or club",
  +            'postcode': 'Postcode',
  +            'country': 'Country',
               }
           widgets = {
  -            'name' : forms.TextInput(attrs={'autocomplete': "off", 'placeholder': 'Name of your school or club'}),
  -            'postcode' : forms.TextInput(attrs={'autocomplete': "off", 'placeholder': 'Postcode'}),
  -            'country' : CountrySelectWidget(attrs={'class': 'wide'}),
  +            'name': forms.TextInput(attrs={'autocomplete': "off", 'placeholder': 'Name of your school or club'}),
  +            'postcode': forms.TextInput(attrs={'autocomplete': "off", 'placeholder': 'Postcode'}),
  +            'country': CountrySelectWidget(attrs={'class': 'wide'}),
               }
   
       def __init__(self, *args, **kwargs):
  @@ -89,9 +89,8 @@
           postcode = self.cleaned_data.get('postcode', None)
   
           if postcode:
  -            # Basic postcode check for now
  -            if not len(postcode.replace(' ', '')) > 0:
  -                raise forms.ValidationError("That postcode was not recognised")
  +            if len(postcode.replace(' ', '')) > 10 or len(postcode.replace(' ', '')) == 0:
  +                raise forms.ValidationError("Please enter a valid postcode or ZIP code")
   
           return postcode
  
verification_info: {"golden_diff": "diff --git a/portal/forms/organisation.py b/portal/forms/organisation.py\n--- a/portal/forms/organisation.py\n+++ b/portal/forms/organisation.py\n@@ -52,14 +52,14 @@\n         model = School\n         fields = ['name', 'postcode', 'country']\n         labels = {\n-            'name' : \"Name of your school or club\",\n-            'postcode' : 'Postcode',\n-            'country' : 'Country',\n+            'name': \"Name of your school or club\",\n+            'postcode': 'Postcode',\n+            'country': 'Country',\n             }\n         widgets = {\n-            'name' : forms.TextInput(attrs={'autocomplete': \"off\", 'placeholder': 'Name of your school or club'}),\n-            'postcode' : forms.TextInput(attrs={'autocomplete': \"off\", 'placeholder': 'Postcode'}),\n-            'country' : CountrySelectWidget(attrs={'class': 'wide'}),\n+            'name': forms.TextInput(attrs={'autocomplete': \"off\", 'placeholder': 'Name of your school or club'}),\n+            'postcode': forms.TextInput(attrs={'autocomplete': \"off\", 'placeholder': 'Postcode'}),\n+            'country': CountrySelectWidget(attrs={'class': 'wide'}),\n             }\n \n     def __init__(self, *args, **kwargs):\n@@ -89,9 +89,8 @@\n         postcode = self.cleaned_data.get('postcode', None)\n \n         if postcode:\n-            # Basic postcode check for now\n-            if not len(postcode.replace(' ', '')) > 0:\n-                raise forms.ValidationError(\"That postcode was not recognised\")\n+            if len(postcode.replace(' ', '')) > 10 or len(postcode.replace(' ', '')) == 0:\n+                raise forms.ValidationError(\"Please enter a valid postcode or ZIP code\")\n \n         return postcode\n", "issue": "Postcode / Zipcode error message at School creation is misleading\nSince most web browsers autocomplete the postcode in the class creation form as the email address, teachers receive a badly worded AND badly positioned error message (the message makes it sound like the error is in the name)\r\nIt should mention something like, please input a valid postcode / zipcode \r\nand be below the postcode field.\n", "before_files": [{"content": "# -*- coding: utf-8 -*-\n# Code for Life\n#\n# Copyright (C) 2017, Ocado Innovation Limited\n#\n# This program is free software: you can redistribute it and/or modify\n# it under the terms of the GNU Affero General Public License as\n# published by the Free Software Foundation, either version 3 of the\n# License, or (at your option) any later version.\n#\n# This program is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU Affero General Public License for more details.\n#\n# You should have received a copy of the GNU Affero General Public License\n# along with this program.  If not, see <http://www.gnu.org/licenses/>.\n#\n# ADDITIONAL TERMS \u2013 Section 7 GNU General Public Licence\n#\n# This licence does not grant any right, title or interest in any \u201cOcado\u201d logos,\n# trade names or the trademark \u201cOcado\u201d or any other trademarks or domain names\n# owned by Ocado Innovation Limited or the Ocado group of companies or any other\n# distinctive brand features of \u201cOcado\u201d as may be secured from time to time. You\n# must not distribute any modification of this program using the trademark\n# \u201cOcado\u201d or claim any affiliation or association with Ocado or its employees.\n#\n# You are not authorised to use the name Ocado (or any of its trade names) or\n# the names of any author or contributor in advertising or for publicity purposes\n# pertaining to the distribution of this program, without the prior written\n# authorisation of Ocado.\n#\n# Any propagation, distribution or conveyance of this program must include this\n# copyright notice and these terms. You must not misrepresent the origins of this\n# program; modified versions of the program must be marked as such and not\n# identified as the original program.\nfrom django import forms\n\nfrom portal.models import School\n\nfrom django_countries.widgets import CountrySelectWidget\nfrom  django.core.exceptions import ObjectDoesNotExist\n\n\nclass OrganisationForm(forms.ModelForm):\n\n    current_password = forms.CharField(\n        label='Enter your password',\n        widget=forms.PasswordInput(attrs={'autocomplete': \"off\"}))\n\n    class Meta:\n        model = School\n        fields = ['name', 'postcode', 'country']\n        labels = {\n            'name' : \"Name of your school or club\",\n            'postcode' : 'Postcode',\n            'country' : 'Country',\n            }\n        widgets = {\n            'name' : forms.TextInput(attrs={'autocomplete': \"off\", 'placeholder': 'Name of your school or club'}),\n            'postcode' : forms.TextInput(attrs={'autocomplete': \"off\", 'placeholder': 'Postcode'}),\n            'country' : CountrySelectWidget(attrs={'class': 'wide'}),\n            }\n\n    def __init__(self, *args, **kwargs):\n        self.user = kwargs.pop('user', None)\n        self.current_school = kwargs.pop('current_school', None)\n        super(OrganisationForm, self).__init__(*args, **kwargs)\n        if self.current_school:\n            del self.fields['current_password']\n\n    def clean(self):\n        name = self.cleaned_data.get('name', None)\n        postcode = self.cleaned_data.get('postcode', None)\n\n        if name and postcode:\n            try:\n                school = School.objects.get(name=name, postcode=postcode)\n            except ObjectDoesNotExist:\n                return self.cleaned_data\n\n            if not self.current_school or self.current_school.id != school.id:\n                raise forms.ValidationError(\n                    \"There is already a school or club registered with that name and postcode\")\n\n        return self.cleaned_data\n\n    def clean_postcode(self):\n        postcode = self.cleaned_data.get('postcode', None)\n\n        if postcode:\n            # Basic postcode check for now\n            if not len(postcode.replace(' ', '')) > 0:\n                raise forms.ValidationError(\"That postcode was not recognised\")\n\n        return postcode\n\n    def clean_current_password(self):\n        current_password = self.cleaned_data.get('current_password', None)\n        if not self.user.check_password(current_password):\n            raise forms.ValidationError(\"Your password was incorrect\")\n\n\nclass OrganisationJoinForm(forms.Form):\n    fuzzy_name = forms.CharField(\n        label=\"Search for school or club by name or postcode\",\n        widget=forms.TextInput(\n            attrs={'placeholder': \"Enrico Fermi High School\"}))\n\n    # Note: the reason this is a CharField rather than a ChoiceField is to avoid having to\n    # provide choices which was problematic given that the options are dynamically generated.\n    chosen_org = forms.CharField(\n        label='Select school or club',\n        widget=forms.Select(attrs={'class': 'wide'}))\n\n    def clean_chosen_org(self):\n        chosen_org = self.cleaned_data.get('chosen_org', None)\n\n        if chosen_org and not School.objects.filter(id=int(chosen_org)).exists():\n            raise forms.ValidationError(\"That school or club was not recognised\")\n\n        return chosen_org\n\n", "path": "portal/forms/organisation.py"}]}