Repository: GeotrekCE/Geotrek-admin

Issue:
Erreur API V2
En 2.50, nouvelle erreur de l'API lors de la consultation via https://randoadmin.parc-haut-jura.fr/api/v2/trek/, j'ai un server error 500 et je reçois l'erreur suivante par mail : 

[Geotrek] ERROR (EXTERNAL IP): Internal Server Error: /api/v2/trek/

Internal Server Error: /api/v2/trek/

TypeError at /api/v2/trek/
Object of type 'LineString' is not JSON serializable

Request Method: GET
Request URL: https://randoadmin.parc-haut-jura.fr/api/v2/trek/
Django Version: 3.1.7
Python Executable: /opt/geotrek-admin/bin/python Python Version: 3.6.9 Python Path: ['/', '/', '/opt/geotrek-admin/bin', '/usr/lib/python36.zip', '/usr/lib/python3.6', '/usr/lib/python3.6/lib-dynload', '/opt/geotrek-admin/lib/python3.6/site-packages']
Server time: Wed, 24 Feb 2021 16:02:24 +0100 Installed Applications:
('modeltranslation',
 'django.contrib.auth',



Discussion:
OK tu dois avoir une rando qui a un problème de géométrie.
Car il est installé en 2.50.0 sur le démo (https://geotrekdemo.ecrins-parcnational.fr/api/v2/) et aussi sur notre serveur de production, sans erreur.
Ok je regarde d'où ca vient alors merci !
Effectivement un itinéraire avec une géométrie invalide faisait bugué l'API, c'est résolu, désolé du dérangement ! 
Thomas
OK c'est cependant pas dérangeant car ça nous indique si une rando a un problème de géométrie, cela ne devrait pas faire péter l'API, mais soit lever une erreur sur la rando concernée, soit l'exclure.

Bon du coup si tu as un Geotrek-admin 2.50.0, tu vas pouvoir tester le déploiement de la V3 de Geotrek-rando que l'on finalise cette semaine. 
Je suis en train de tester et compléter la documentation aujourd'hui : https://github.com/GeotrekCE/Geotrek-rando-v3/blob/main/docs/installation.md
Avec aussi un premier aperçu du Changelog : https://github.com/GeotrekCE/Geotrek-rando-v3/blob/main/docs/changelog.md

Resolving patch:
diff --git a/geotrek/api/v2/serializers.py b/geotrek/api/v2/serializers.py
--- a/geotrek/api/v2/serializers.py
+++ b/geotrek/api/v2/serializers.py
@@ -416,7 +416,7 @@ def get_departure(self, obj):
             return get_translation_or_dict('departure', self, obj)
 
         def get_departure_geom(self, obj):
-            return obj.geom_3d[0][0] if isinstance(obj, MultiLineString) else obj.geom_3d[0]
+            return obj.geom_3d[0][0] if isinstance(obj.geom_3d, MultiLineString) else obj.geom_3d[0]
 
         def get_arrival(self, obj):
             return get_translation_or_dict('arrival', self, obj)


Test patch:
diff --git a/geotrek/api/tests/test_v2.py b/geotrek/api/tests/test_v2.py
--- a/geotrek/api/tests/test_v2.py
+++ b/geotrek/api/tests/test_v2.py
@@ -1,4 +1,5 @@
 from django.contrib.auth.models import User
+from django.contrib.gis.geos import MultiLineString
 from django.urls import reverse
 from django.test.client import Client
 from django.test.testcases import TestCase
@@ -159,7 +160,6 @@ def setUpTestData(cls):
         cls.theme = common_factory.ThemeFactory(id=15)
         cls.portal = common_factory.TargetPortalFactory(id=16)
         cls.structure = authent_factory.StructureFactory(id=8)
-        cls.nb_treks += 2  # add parent and 1 child published
         cls.poi_type = trek_factory.POITypeFactory()
         cls.poi = trek_factory.POIFactory()
         cls.source = common_factory.RecordSourceFactory()
@@ -167,6 +167,18 @@ def setUpTestData(cls):
         cls.site = outdoor_factory.SiteFactory()
         cls.category = tourism_factory.TouristicContentCategoryFactory()
         common_factory.FileTypeFactory.create(type='Topoguide')
+        # Create a trek with a multilinestring geom
+        cls.path2 = core_factory.PathFactory.create(geom=LineString((0, 10), (0, 20)))
+        cls.path3 = core_factory.PathFactory.create(geom=LineString((0, 20), (0, 30)))
+        cls.trek_multilinestring = trek_factory.TrekFactory.create(
+            paths=[(cls.path, 0, 1), (cls.path2, 0, 1), (cls.path3, 0, 1)],
+            geom=MultiLineString([cls.path.geom, cls.path3.geom])
+        )
+        cls.path2.delete()
+        cls.trek_multilinestring.reload()
+        cls.trek_multilinestring.published = True
+        cls.trek_multilinestring.save()
+        cls.nb_treks += 3  # add parent, 1 child published and rek with a multilinestring geom
 
     def check_number_elems_response(self, response, model):
         json_response = response.json()
@@ -344,7 +356,7 @@ def test_trek_list(self):
         self.assertEqual(len(json_response.get('results')[0].get('geometry').get('coordinates')[0]),
                          3)
 
-        # regenrate with geojson
+        # regenerate with geojson
         response = self.get_trek_list({'format': 'geojson'})
         json_response = response.json()
 
@@ -403,7 +415,7 @@ def test_trek_list_filters_inexistant_zones(self):
 
     def test_trek_city(self):
         response = self.get_trek_list({'cities': self.city.pk})
-        self.assertEqual(len(response.json()['results']), 15)
+        self.assertEqual(len(response.json()['results']), 16)
 
     def test_tour_list(self):
         response = self.get_tour_list()