Skip to content

Commit

Permalink
Include tags and attributes in csv file download (#4112)
Browse files Browse the repository at this point in the history
  • Loading branch information
dimasciput authored Jul 25, 2024
1 parent 30f6eba commit 9e310a9
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 33 deletions.
5 changes: 4 additions & 1 deletion bims/tasks/download_taxa_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ def __init__(self, get_data):
# Get the taxa list based on request parameters
taxa_list = TaxaList.get_taxa_by_parameters(request_get)

tag_titles = []

# Define the header update function
def update_headers(_headers):
_updated_headers = []
Expand All @@ -34,7 +36,7 @@ def update_headers(_headers):
elif header == 'common_name':
header = 'Common Name'
header = header.replace('_or_', '/')
if not header.istitle():
if not header.istitle() and header not in tag_titles:
header = header.replace('_', ' ').capitalize()
if header == 'Sub species':
header = 'SubSpecies'
Expand All @@ -44,6 +46,7 @@ def update_headers(_headers):
# Serialize a single item to extract headers
sample_item = next(taxa_list.iterator())
sample_serializer = TaxaCSVSerializer(sample_item)
tag_titles = sample_serializer.context.get('tags', [])
headers = list(sample_serializer.data.keys())
updated_headers = update_headers(headers)

Expand Down
70 changes: 69 additions & 1 deletion bims/tests/test_taxa.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
from django.test import TestCase

from bims.enums import TaxonomicGroupCategory
from bims.tests.model_factories import (
TaxonomyF, BiologicalCollectionRecordF, TaxonGroupF, VernacularNameF
)
from bims.utils.fetch_gbif import merge_taxa_data
from bims.models import Taxonomy, BiologicalCollectionRecord, TaxonGroup
from bims.models import Taxonomy, BiologicalCollectionRecord, TaxonGroup, IUCNStatus, TaxonExtraAttribute
from bims.views.download_csv_taxa_list import TaxaCSVSerializer


class TestTaxaHelpers(TestCase):
Expand Down Expand Up @@ -86,3 +89,68 @@ def test_merge_duplicated_taxa(self):
Taxonomy.objects.get(id=taxa_2.id).vernacular_names.all().count(),
3
)


class TaxaCSVSerializerTest(TestCase):
def setUp(self):
self.taxon_group = TaxonGroupF.create(
category=TaxonomicGroupCategory.SPECIES_MODULE.name)

self.vernacular_name = VernacularNameF(
name='Human',
language='en'
)
self.taxonomy = TaxonomyF.create(
rank='SPECIES',
canonical_name='Homo sapiens',
scientific_name='Homo sapiens Linnaeus',
endemism=None,
iucn_status=IUCNStatus.objects.create(category='LC'),
national_conservation_status=IUCNStatus.objects.create(category='NT'),
gbif_key='12345',
additional_data={'Growth form': 'Tree'},
vernacular_names=(self.vernacular_name,)
)
self.taxonomy.tags.add('freshwater', 'testing')
self.taxonomy.biographic_distributions.add('ANT', 'TEST (?)')

self.taxon_group.taxonomies.add(self.taxonomy)
self.taxon_extra_attribute = TaxonExtraAttribute.objects.create(
taxon_group=self.taxon_group,
name='Growth form'
)

def test_serializer_fields(self):
serializer = TaxaCSVSerializer(instance=self.taxonomy)
serialized_data = serializer.data

expected_fields = [
'taxon_rank', 'kingdom', 'phylum', 'class_name', 'order', 'family', 'genus', 'species',
'sub_species', 'taxon', 'scientific_name_and_authority', 'common_name', 'origin',
'endemism', 'conservation_status_global', 'conservation_status_national', 'on_gbif', 'gbif_link',
'Growth form', 'freshwater', 'testing', 'ANT'
]

for field in expected_fields:
self.assertIn(field, serialized_data)

def test_serializer_values(self):
serializer = TaxaCSVSerializer(instance=self.taxonomy)
serialized_data = serializer.data

self.assertEqual(serialized_data['taxon_rank'], 'Species')
self.assertEqual(serialized_data['species'], 'Homo sapiens')
self.assertEqual(serialized_data['taxon'], 'Homo sapiens')
self.assertEqual(serialized_data['scientific_name_and_authority'], 'Homo sapiens Linnaeus')
self.assertEqual(serialized_data['common_name'], 'Human')
self.assertEqual(serialized_data['endemism'], 'Unknown')
self.assertEqual(serialized_data['conservation_status_global'], 'Least Concern')
self.assertEqual(serialized_data['conservation_status_national'], 'Near Threatened')
self.assertEqual(serialized_data['on_gbif'], 'Yes')
self.assertEqual(serialized_data['gbif_link'], 'https://www.gbif.org/species/12345')
self.assertEqual(serialized_data['Growth form'], 'Tree')
self.assertEqual(serialized_data['freshwater'], 'Y')
self.assertEqual(serialized_data['testing'], 'Y')
self.assertEqual(serialized_data['ANT'], 'Y')
self.assertEqual(serialized_data['TEST'], '?')
self.assertTrue(len(serializer.context.get('tags')) > 0)
66 changes: 35 additions & 31 deletions bims/views/download_csv_taxa_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,9 @@ def get_scientific_name_and_authority(self, obj):

def get_common_name(self, obj):
vernacular_names = list(
obj.vernacular_names.filter(language__istartswith='en').values_list('name', flat=True))
obj.vernacular_names.filter(
language__istartswith='en'
).values_list('name', flat=True))
if len(vernacular_names) == 0:
return ''
else:
Expand Down Expand Up @@ -157,47 +159,49 @@ def __init__(self, *args, **kwargs):
super(TaxaCSVSerializer, self).__init__(*args, **kwargs)
self.context['headers'] = []
self.context['additional_data'] = []
self.context['tags'] = []

def to_representation(self, instance):
result = super(
TaxaCSVSerializer, self).to_representation(
instance)
def _ensure_headers(self, keys):
if 'headers' not in self.context:
self.context['headers'] = list(result.keys())
self.context['headers'] = list(keys)

def _add_additional_attributes(self, instance, result):
taxon_group = TaxonGroup.objects.filter(
category=TaxonomicGroupCategory.SPECIES_MODULE.name,
taxonomies__in=[instance]).first()
taxonomies__in=[instance]
).first()

if taxon_group:
taxon_extra_attributes = TaxonExtraAttribute.objects.filter(
taxon_group=taxon_group
)
if taxon_extra_attributes.exists():
for taxon_extra_attribute in taxon_extra_attributes:
taxon_attribute_name = taxon_extra_attribute.name
if taxon_attribute_name not in self.context['headers']:
self.context['headers'].append(taxon_attribute_name)
try:
if (
taxon_attribute_name == 'Growth form'
):
if (
taxon_attribute_name not in
instance.additional_data or
instance.additional_data[
taxon_attribute_name] == ''
):
taxon_attribute_name = 'Growth Form'
if taxon_attribute_name in instance.additional_data:
result[taxon_attribute_name] = (
instance.additional_data[taxon_attribute_name]
)
else:
result[taxon_attribute_name] = ''
except TypeError:
result[taxon_attribute_name] = ''
for taxon_extra_attribute in taxon_extra_attributes:
attribute_name = taxon_extra_attribute.name
if attribute_name not in self.context['headers']:
self.context['headers'].append(attribute_name)
if instance.additional_data:
result[attribute_name] = (
instance.additional_data.get(attribute_name, '')
)

def _add_tags(self, instance, result):
all_tags = list(instance.tags.all()) + list(instance.biographic_distributions.all())
for tag in all_tags:
tag_name = tag.name.strip()
tag_value = 'Y'
if '(?)' in tag_name:
tag_value = '?'
tag_name = tag_name.replace('(?)', '').strip()
if tag_name not in self.context['headers']:
self.context['headers'].append(tag_name)
self.context['tags'].append(tag_name)
result[tag_name] = tag_value

def to_representation(self, instance):
result = super().to_representation(instance)
self._ensure_headers(result.keys())
self._add_additional_attributes(instance, result)
self._add_tags(instance, result)
return result


Expand Down

0 comments on commit 9e310a9

Please sign in to comment.