Skip to content

Commit

Permalink
✨ [FEAT] Add UUIDs of parent and children Courses and Sites in APIv2 …
Browse files Browse the repository at this point in the history
…(refs #3569)
  • Loading branch information
Chatewgne committed Jan 22, 2024
1 parent 47a85b1 commit 76412f2
Show file tree
Hide file tree
Showing 3 changed files with 193 additions and 20 deletions.
7 changes: 6 additions & 1 deletion docs/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,17 @@ CHANGELOG
2.101.5+dev (XXXX-XX-XX)
------------------------

**New features**

- Add UUIDs of parent and children ``Courses`` and ``Sites`` in APIv2 (#3569)


2.101.5 (2024-01-11)
--------------------

**New features**

-Land: Add ``CirculationEdge`` model to manage circulation types and authorization types in the land module (#3578)
- Land: Add ``CirculationEdge`` model to manage circulation types and authorization types in the land module (#3578)
- Generalize``AccessMean`` model and add field ``access`` to ``Intervention`` (#3819)

**Improvements**
Expand Down
55 changes: 49 additions & 6 deletions geotrek/api/tests/test_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,9 +158,9 @@
RESERVATION_SYSTEM_PROPERTIES_JSON_STRUCTURE = sorted(['name', 'id'])

SITE_PROPERTIES_JSON_STRUCTURE = sorted([
'accessibility', 'advice', 'ambiance', 'attachments', 'children', 'cities', 'courses', 'description', 'description_teaser', 'districts', 'eid',
'geometry', 'id', 'information_desks', 'labels', 'managers', 'name', 'orientation', 'parent', 'period', 'portal',
'practice', 'provider', 'pdf', 'ratings', 'sector', 'source', 'structure', 'themes', 'type', 'url', 'uuid',
'accessibility', 'advice', 'ambiance', 'attachments', 'children', 'children_uuids', 'cities', 'courses', 'courses_uuids', 'description',
'description_teaser', 'districts', 'eid', 'geometry', 'id', 'information_desks', 'labels', 'managers', 'name', 'orientation', 'parent',
'parent_uuid', 'period', 'portal', 'practice', 'provider', 'pdf', 'ratings', 'sector', 'source', 'structure', 'themes', 'type', 'url', 'uuid',
'view_points', 'wind', 'web_links'
])

Expand All @@ -186,9 +186,9 @@

COURSE_PROPERTIES_JSON_STRUCTURE = sorted([
'accessibility', 'advice', 'cities', 'description', 'districts', 'eid', 'equipment', 'geometry', 'height', 'id',
'length', 'name', 'ratings', 'ratings_description', 'sites', 'structure',
'type', 'url', 'attachments', 'max_elevation', 'min_elevation', 'parents', 'provider',
'pdf', 'points_reference', 'children', 'duration', 'gear', 'uuid'
'length', 'name', 'ratings', 'ratings_description', 'sites', 'sites_uuids', 'structure',
'type', 'url', 'attachments', 'max_elevation', 'min_elevation', 'parents', 'parents_uuids', 'provider',
'pdf', 'points_reference', 'children', 'children_uuids', 'duration', 'gear', 'uuid'
])

COURSETYPE_PROPERTIES_JSON_STRUCTURE = sorted(['id', 'name', 'practice'])
Expand Down Expand Up @@ -4429,6 +4429,11 @@ def test_site_children_published_serializing(self):
self.assertIn(self.site_leaf_published.pk, children)
self.assertIn(self.site_leaf_published_2.pk, children)
self.assertNotIn(self.site_leaf_unpublished.pk, children)
children_uuids = response.json()['children_uuids']
self.assertEqual(2, len(children_uuids))
self.assertIn(str(self.site_leaf_published.uuid), children_uuids)
self.assertIn(str(self.site_leaf_published_2.uuid), children_uuids)
self.assertNotIn(str(self.site_leaf_unpublished.uuid), children_uuids)

def test_site_parent_unpublished_serializing(self):
response = self.get_site_detail(self.site_node_parent_unpublished.pk)
Expand All @@ -4448,8 +4453,15 @@ def test_site_parent_and_children_serializing_by_lang(self):
self.assertIn(self.site_leaf_published_fr.pk, children)
self.assertNotIn(self.site_leaf_published_not_fr.pk, children)
self.assertNotIn(self.site_leaf_unpublished_fr.pk, children)
children_uuids = site_published_fr['children_uuids']
self.assertEqual(1, len(children_uuids))
self.assertIn(str(self.site_leaf_published_fr.uuid), children_uuids)
self.assertNotIn(str(self.site_leaf_published_not_fr.uuid), children_uuids)
self.assertNotIn(str(self.site_leaf_unpublished_fr.uuid), children_uuids)
parent = site_published_fr['parent']
parent_uuid = site_published_fr['parent_uuid']
self.assertEqual(parent, self.site_root_fr.pk)
self.assertEqual(parent_uuid, str(self.site_root_fr.uuid))


class OutdoorFilterByPracticesTestCase(BaseApiTest):
Expand Down Expand Up @@ -4509,6 +4521,9 @@ def setUpTestData(cls):
cls.course = outdoor_factory.CourseFactory()
cls.course.parent_sites.set([cls.site.pk])
cls.course2 = outdoor_factory.CourseFactory()
cls.course3 = outdoor_factory.CourseFactory()
outdoor_models.OrderedCourseChild.objects.create(parent=cls.course, child=cls.course2)
outdoor_models.OrderedCourseChild.objects.create(parent=cls.course3, child=cls.course)
cls.information_desk = tourism_factory.InformationDeskFactory()
cls.site.information_desks.set([cls.information_desk])

Expand All @@ -4522,6 +4537,34 @@ def test_filter_courses_by_portal(self):
self.assertIn(self.course.pk, all_ids)
self.assertNotIn(self.course2.pk, all_ids)

def test_course_serialized_parent_site_and_related_courses(self):
response = self.get_course_detail(self.course.pk)
self.assertEqual(response.status_code, 200)
parent_sites_pk = response.json()['sites']
parent_sites_uuid = response.json()['sites_uuids']
parent_courses_uuid = response.json()['parents_uuids']
parent_courses_pk = response.json()['parents']
children_courses_uuid = response.json()['children_uuids']
children_courses_pk = response.json()['children']
self.assertEqual(parent_sites_pk, [self.site.pk])
self.assertEqual(parent_sites_uuid, [str(self.site.uuid)])
self.assertEqual(parent_courses_pk, [{'order': 0, 'course': self.course3.pk}])
self.assertEqual(parent_courses_uuid, [{'order': 0, 'course': str(self.course3.uuid)}])
self.assertEqual(children_courses_pk, [{'order': 0, 'course': self.course2.pk}])
self.assertEqual(children_courses_uuid, [{'order': 0, 'course': str(self.course2.uuid)}])
response = self.get_course_detail(self.course.pk, params={'language': 'en'})
self.assertEqual(response.status_code, 200)
self.assertEqual(parent_courses_uuid, [{'order': 0, 'course': str(self.course3.uuid)}])
self.assertEqual(children_courses_uuid, [{'order': 0, 'course': str(self.course2.uuid)}])

def test_site_serialized_children_course(self):
response = self.get_site_detail(self.site.pk)
self.assertEqual(response.status_code, 200)
child_course_pk = response.json()['courses']
child_course_uuid = response.json()['courses_uuids']
self.assertEqual(child_course_pk, [self.course.pk])
self.assertEqual(child_course_uuid, [str(self.course.uuid)])

def test_filter_courses_by_themes(self):
response = self.get_course_list({'themes': self.theme.pk})
self.assertEqual(response.status_code, 200)
Expand Down
151 changes: 138 additions & 13 deletions geotrek/api/v2/serializers.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from bs4 import BeautifulSoup
import json

from bs4 import BeautifulSoup
from django.conf import settings
from django.contrib.gis.db.models.functions import Transform
from django.contrib.gis.geos import MultiLineString, Point
Expand All @@ -13,6 +13,7 @@
from easy_thumbnails.engine import NoSourceGenerator
from easy_thumbnails.exceptions import InvalidImageFormatError
from easy_thumbnails.files import get_thumbnailer
from modeltranslation.utils import build_localized_fieldname
from PIL.Image import DecompressionBombError
from rest_framework import serializers
from rest_framework.relations import HyperlinkedIdentityField
Expand Down Expand Up @@ -1144,8 +1145,11 @@ class SiteSerializer(PDFSerializerMixin, DynamicFieldsMixin, serializers.ModelSe
attachments = AttachmentSerializer(many=True)
sector = serializers.SerializerMethodField()
courses = serializers.SerializerMethodField()
courses_uuids = serializers.SerializerMethodField()
children = serializers.SerializerMethodField()
children_uuids = serializers.SerializerMethodField()
parent = serializers.SerializerMethodField()
parent_uuid = serializers.SerializerMethodField()
pdf = serializers.SerializerMethodField('get_pdf_url')
cities = serializers.SerializerMethodField()
districts = serializers.SerializerMethodField()
Expand All @@ -1168,40 +1172,80 @@ def get_courses(self, obj):
language = request.GET.get('language')
for course in obj.children_courses.all():
if language:
if getattr(course, f"published_{language}"):
if getattr(course, build_localized_fieldname('published', language)):
courses.append(course.pk)
else:
if course.published:
courses.append(course.pk)
return courses

def get_courses_uuids(self, obj):
courses = []
request = self.context['request']
language = request.GET.get('language')
for course in obj.children_courses.all():
if language:
if getattr(course, build_localized_fieldname('published', language)):
courses.append(course.uuid)
else:
if course.published:
courses.append(course.uuid)
return courses

def get_parent(self, obj):
parent = None
request = self.context['request']
language = request.GET.get('language')
if obj.parent:
if language:
if getattr(obj.parent, f"published_{language}"):
if getattr(obj.parent, build_localized_fieldname('published', language)):
parent = obj.parent.pk
else:
if obj.parent.published:
parent = obj.parent.pk
return parent

def get_parent_uuid(self, obj):
parent = None
request = self.context['request']
language = request.GET.get('language')
if obj.parent:
if language:
if getattr(obj.parent, build_localized_fieldname('published', language)):
parent = obj.parent.uuid
else:
if obj.parent.published:
parent = obj.parent.uuid
return parent

def get_children(self, obj):
children = []
request = self.context['request']
language = request.GET.get('language')
if language:
for site in obj.get_children():
if getattr(site, f"published_{language}"):
if getattr(site, build_localized_fieldname('published', language)):
children.append(site.pk)
else:
for site in obj.get_children():
if site.published:
children.append(site.pk)
return children

def get_children_uuids(self, obj):
children = []
request = self.context['request']
language = request.GET.get('language')
if language:
for site in obj.get_children():
if getattr(site, build_localized_fieldname('published', language)):
children.append(site.uuid)
else:
for site in obj.get_children():
if site.published:
children.append(site.uuid)
return children

def get_sector(self, obj):
if obj.practice and obj.practice.sector:
return obj.practice.sector_id
Expand All @@ -1210,24 +1254,27 @@ def get_sector(self, obj):
class Meta:
model = outdoor_models.Site
fields = (
'id', 'accessibility', 'advice', 'ambiance', 'attachments', 'cities', 'children', 'description',
'id', 'accessibility', 'advice', 'ambiance', 'attachments', 'cities', 'children', 'children_uuids', 'description',
'description_teaser', 'districts', 'eid', 'geometry', 'information_desks', 'labels', 'managers',
'name', 'orientation', 'pdf', 'period', 'parent', 'portal', 'practice', 'provider',
'name', 'orientation', 'pdf', 'period', 'parent', 'parent_uuid', 'portal', 'practice', 'provider',
'ratings', 'sector', 'source', 'structure', 'themes', 'view_points',
'type', 'url', 'uuid', 'courses', 'web_links', 'wind',
'type', 'url', 'uuid', 'courses', 'courses_uuids', 'web_links', 'wind',
)

class CourseSerializer(PDFSerializerMixin, DynamicFieldsMixin, serializers.ModelSerializer):
url = HyperlinkedIdentityField(view_name='apiv2:course-detail')
geometry = geo_serializers.GeometryField(read_only=True, source="geom_transformed", precision=7)
children = serializers.ReadOnlyField(source='children_id')
parents = serializers.ReadOnlyField(source='parents_id')
children = serializers.SerializerMethodField()
parents = serializers.SerializerMethodField()
parents_uuids = serializers.SerializerMethodField()
children_uuids = serializers.SerializerMethodField()
accessibility = serializers.SerializerMethodField()
attachments = AttachmentSerializer(many=True, source='sorted_attachments')
equipment = serializers.SerializerMethodField()
gear = serializers.SerializerMethodField()
ratings_description = serializers.SerializerMethodField()
sites = serializers.SerializerMethodField()
sites_uuids = serializers.SerializerMethodField()
points_reference = serializers.SerializerMethodField()
pdf = serializers.SerializerMethodField('get_pdf_url')
cities = serializers.SerializerMethodField()
Expand Down Expand Up @@ -1257,14 +1304,92 @@ def get_sites(self, obj):
language = request.GET.get('language')
if language:
for site in obj.parent_sites.all():
if getattr(site, f"published_{language}"):
if getattr(site, build_localized_fieldname('published', language)):
sites.append(site.pk)
else:
for site in obj.parent_sites.all():
if getattr(site, "published"):
sites.append(site.pk)
return sites

def get_children(self, obj):
courses = []
request = self.context['request']
language = request.GET.get('language')
if language:
for ordered_child in obj.course_children.order_by('order'):
course = ordered_child.child
if getattr(course, build_localized_fieldname('published', language)):
courses.append({'order': ordered_child.order, 'course': course.pk})
else:
for ordered_child in obj.course_children.order_by('order'):
course = ordered_child.child
if getattr(course, "published"):
courses.append({'order': ordered_child.order, 'course': course.pk})
return courses

def get_parents(self, obj):
courses = []
request = self.context['request']
language = request.GET.get('language')
if language:
for ordered_parent in obj.course_parents.order_by('order'):
course = ordered_parent.parent
if getattr(course, build_localized_fieldname('published', language)):
courses.append({'order': ordered_parent.order, 'course': course.pk})
else:
for ordered_parent in obj.course_parents.order_by('order'):
course = ordered_parent.parent
if getattr(course, "published"):
courses.append({'order': ordered_parent.order, 'course': course.pk})
return courses

def get_children_uuids(self, obj):
courses = []
request = self.context['request']
language = request.GET.get('language')
if language:
for ordered_child in obj.course_children.order_by('order'):
course = ordered_child.child
if getattr(course, build_localized_fieldname('published', language)):
courses.append({'order': ordered_child.order, 'course': course.uuid})
else:
for ordered_child in obj.course_children.order_by('order'):
course = ordered_child.child
if getattr(course, "published"):
courses.append({'order': ordered_child.order, 'course': course.uuid})
return courses

def get_parents_uuids(self, obj):
courses = []
request = self.context['request']
language = request.GET.get('language')
if language:
for ordered_parent in obj.course_parents.order_by('order'):
course = ordered_parent.parent
if getattr(course, build_localized_fieldname('published', language)):
courses.append({'order': ordered_parent.order, 'course': course.uuid})
else:
for ordered_parent in obj.course_parents.order_by('order'):
course = ordered_parent.parent
if getattr(course, "published"):
courses.append({'order': ordered_parent.order, 'course': course.uuid})
return courses

def get_sites_uuids(self, obj):
sites = []
request = self.context['request']
language = request.GET.get('language')
if language:
for site in obj.parent_sites.all():
if getattr(site, build_localized_fieldname('published', language)):
sites.append(site.uuid)
else:
for site in obj.parent_sites.all():
if getattr(site, "published"):
sites.append(site.uuid)
return sites

def get_points_reference(self, obj):
if not obj.points_reference:
return None
Expand All @@ -1274,10 +1399,10 @@ def get_points_reference(self, obj):
class Meta:
model = outdoor_models.Course
fields = (
'id', 'accessibility', 'advice', 'attachments', 'children', 'cities', 'description', 'districts', 'duration', 'eid',
'id', 'accessibility', 'advice', 'attachments', 'children', 'children_uuids', 'cities', 'description', 'districts', 'duration', 'eid',
'equipment', 'gear', 'geometry', 'height', 'length', 'max_elevation',
'min_elevation', 'name', 'parents', 'pdf', 'points_reference', 'provider', 'ratings', 'ratings_description',
'sites', 'structure', 'type', 'url', 'uuid'
'min_elevation', 'name', 'parents', 'parents_uuids', 'pdf', 'points_reference', 'provider', 'ratings', 'ratings_description',
'sites', 'sites_uuids', 'structure', 'type', 'url', 'uuid'
)

if 'geotrek.feedback' in settings.INSTALLED_APPS:
Expand Down

0 comments on commit 76412f2

Please sign in to comment.