Repository: akvo/akvo-rsr

Issue:
UnicodeDecodeError in /rest/v1/project_location end-point



Discussion:

Resolving patch:
diff --git a/akvo/rsr/models/location.py b/akvo/rsr/models/location.py
--- a/akvo/rsr/models/location.py
+++ b/akvo/rsr/models/location.py
@@ -94,7 +94,7 @@ def iati_country_value(self):
         return codelist_value(Country, self, 'iati_country')
 
     def iati_country_value_unicode(self):
-        return str(self.iati_country_value())
+        return unicode(self.iati_country_value())
 
 
 class ProjectLocation(BaseLocation):
@@ -170,10 +170,10 @@ def __unicode__(self):
         return u'{0}, {1}{2}'.format(
             u'{0}: {1}'.format(
                 _(u'Latitude'),
-                str(self.latitude) if self.latitude else _(u'No latitude specified')),
+                unicode(self.latitude) if self.latitude else _(u'No latitude specified')),
             u'{0}: {1}'.format(
                 _(u'Longitude'),
-                str(self.longitude) if self.longitude else _(u'No longitude specified')),
+                unicode(self.longitude) if self.longitude else _(u'No longitude specified')),
             u' ({0})'.format(self.name) if self.name else u''
         )
 
@@ -181,37 +181,37 @@ def iati_country(self):
         return codelist_value(Country, self, 'country')
 
     def iati_country_unicode(self):
-        return str(self.iati_country())
+        return unicode(self.iati_country())
 
     def iati_vocabulary(self):
         return codelist_value(GeographicVocabulary, self, 'vocabulary')
 
     def iati_vocabulary_unicode(self):
-        return str(self.iati_vocabulary())
+        return unicode(self.iati_vocabulary())
 
     def iati_exactness(self):
         return codelist_value(GeographicExactness, self, 'exactness')
 
     def iati_exactness_unicode(self):
-        return str(self.iati_exactness())
+        return unicode(self.iati_exactness())
 
     def iati_reach(self):
         return codelist_value(GeographicLocationReach, self, 'location_reach')
 
     def iati_reach_unicode(self):
-        return str(self.iati_reach())
+        return unicode(self.iati_reach())
 
     def iati_class(self):
         return codelist_value(GeographicLocationClass, self, 'location_class')
 
     def iati_class_unicode(self):
-        return str(self.iati_class())
+        return unicode(self.iati_class())
 
     def iati_designation(self):
         return codelist_value(LocationType, self, 'feature_designation')
 
     def iati_designation_unicode(self):
-        return str(self.iati_designation())
+        return unicode(self.iati_designation())
 
 # Over-riding fields doesn't work in Django < 1.10, and hence this hack.
 ProjectLocation._meta.get_field('country').help_text = _(
@@ -240,13 +240,13 @@ class AdministrativeLocation(models.Model):
     level = models.PositiveSmallIntegerField(_(u'administrative level'), blank=True, null=True)
 
     def __unicode__(self):
-        return str(self.code) if self.code else u'%s' % _(u'No code specified')
+        return unicode(self.code) if self.code else u'%s' % _(u'No code specified')
 
     def iati_vocabulary(self):
         return codelist_value(GeographicVocabulary, self, 'vocabulary')
 
     def iati_vocabulary_unicode(self):
-        return str(self.iati_vocabulary())
+        return unicode(self.iati_vocabulary())
 
     class Meta:
         app_label = 'rsr'


Test patch:
diff --git a/akvo/rsr/tests/rest/test_project_location.py b/akvo/rsr/tests/rest/test_project_location.py
new file mode 100644
--- /dev/null
+++ b/akvo/rsr/tests/rest/test_project_location.py
@@ -0,0 +1,39 @@
+# -*- coding: utf-8 -*-
+
+"""
+Akvo RSR is covered by the GNU Affero General Public License.
+
+See more details in the license.txt file located at the root folder of the Akvo RSR module.
+For additional details on the GNU license please see < http://www.gnu.org/licenses/agpl.html >.
+"""
+
+import json
+
+from django.conf import settings
+from django.test import Client, TestCase
+
+from akvo.rsr.models import Country, Project, ProjectLocation
+
+
+class ProjectLocationTest(TestCase):
+
+    def setUp(self):
+        self.c = Client(HTTP_HOST=settings.RSR_DOMAIN)
+
+    def test_project_location_with_unicode_country(self):
+        # Given
+        country_name = u"Côte D'ivoire"
+        project = Project.objects.create()
+        country = Country.objects.create(name=country_name, iso_code='CI')
+        ProjectLocation.objects.create(location_target=project, country=country)
+        url = '/rest/v1/project_location/'
+        data = {'format': 'json', 'location_target': project.id}
+
+        # When
+        response = self.c.get(url, data)
+
+        # Then
+        self.assertEqual(response.status_code, 200)
+        results = json.loads(response.content)['results']
+        self.assertEqual(1, len(results))
+        self.assertEqual(country_name, results[0]['country_label'])