Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file.
71 changes: 71 additions & 0 deletions specifyweb/backend/barvis/tests/test_views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
from specifyweb.specify.models import Collection, Determination, Taxon, Taxontreedefitem
from specifyweb.specify.tests.test_api import ApiTests

from specifyweb.backend.barvis.views import get_taxon_bar_data


class TaxonBarTests(ApiTests):
def setUp(self):
super().setUp()
self.discipline.taxontreedef = self.taxontreedef
self.discipline.save()
self.taxontreedef.discipline = self.discipline
self.taxontreedef.save()

root_rank = Taxontreedefitem.objects.create(
name='Root', rankid=0, treedef=self.taxontreedef
)
species_rank = Taxontreedefitem.objects.create(
name='Species', rankid=220, parent=root_rank, treedef=self.taxontreedef
)
self.root = Taxon.objects.create(
name='Root', rankid=0, definition=self.taxontreedef,
definitionitem=root_rank,
)
self.taxon = Taxon.objects.create(
name='Test species', rankid=220, parent=self.root,
definition=self.taxontreedef, definitionitem=species_rank,
)

def test_returns_current_determination_counts_without_changing_rows(self):
collection_2 = Collection.objects.create(
catalognumformatname='test',
collectionname='TestCollection2',
isembeddedcollectingevent=False,
discipline=self.discipline,
)
Determination.objects.create(
collectionobject=self.collectionobjects[0], taxon=self.taxon,
collectionmemberid=self.collection.id, iscurrent=True,
createdbyagent=self.agent, modifiedbyagent=self.agent,
)
Determination.objects.create(
collectionobject=self.collectionobjects[1], taxon=self.taxon,
collectionmemberid=self.collection.id, iscurrent=True,
createdbyagent=self.agent, modifiedbyagent=self.agent,
)
Determination.objects.bulk_create([
Determination(
collectionobject=self.collectionobjects[0], taxon=self.taxon,
collectionmemberid=self.collection.id, iscurrent=True,
createdbyagent=self.agent, modifiedbyagent=self.agent,
),
])
Determination.objects.create(
collectionobject=self.collectionobjects[2], taxon=self.taxon,
collectionmemberid=self.collection.id, iscurrent=False,
createdbyagent=self.agent, modifiedbyagent=self.agent,
)
Determination.objects.create(
collectionobject=self.collectionobjects[2], taxon=self.taxon,
collectionmemberid=collection_2.id, iscurrent=True,
createdbyagent=self.agent, modifiedbyagent=self.agent,
)

self.assertCountEqual(
get_taxon_bar_data(self.collection),
[
(self.root.id, 0, None, 'Root', 0),
(self.taxon.id, 220, self.root.id, 'Test species', 2),
],
)
82 changes: 34 additions & 48 deletions specifyweb/backend/barvis/views.py
Original file line number Diff line number Diff line change
@@ -1,60 +1,46 @@
from django.db.models import Count, IntegerField, OuterRef, Subquery
from django.db.models.functions import Coalesce
from django.http import HttpResponse
from django.db.models import Count, Q

from specifyweb.middleware.general import require_GET
from specifyweb.specify.views import login_maybe_required
from specifyweb.specify.api.filter_by_col import filter_by_collection
from specifyweb.specify.api.serializers import toJson
from specifyweb.specify.models import Taxon
from specifyweb.specify.models import Determination, Taxon
from specifyweb.specify.views import login_maybe_required

from django.db import connection

def get_taxon_bar_data(collection):
"""Return taxon tile rows with a correlated current-count lookup."""
current_determination_counts = (
Determination.objects
.filter(
taxon_id=OuterRef('pk'),
collectionmemberid=collection.id,
iscurrent=True,
)
.values('taxon_id')
.annotate(count=Count('collectionobject', distinct=True))
.values('count')
Comment thread
coderabbitai[bot] marked this conversation as resolved.
)
taxons = Taxon.objects.annotate(
current_determination_count=Coalesce(
Subquery(
current_determination_counts,
output_field=IntegerField(),
),
0,
)
).values_list(
'id', 'rankid', 'parent_id', 'name', 'current_determination_count'
)
return list(filter_by_collection(taxons, collection))


@require_GET
@login_maybe_required
def taxon_bar(request):
# "Returns the data for creating a taxon tiles visualization."
# cursor = connection.cursor()
# cursor.execute("""
# SELECT t.TaxonID,
# t.RankID,
# t.ParentID,
# t.Name,
# (SELECT COUNT(*) FROM determination d WHERE t.TaxonID = d.TaxonID AND d.IsCurrent = 1)
# FROM taxon t
# WHERE t.TaxonTreeDefID = %s
# """, [request.specify_collection.discipline.taxontreedef_id])

# Implementing the previous SQL query in Django ORM:
taxons = (
Taxon.objects.annotate(
current_determination_count=Count(
'determinations', filter=Q(determinations__iscurrent=True))
)
.values_list("id", "rankid", "parent_id", "name", "current_determination_count")
"""Return the data for creating a taxon tiles visualization."""
return HttpResponse(
toJson(get_taxon_bar_data(request.specify_collection)),
content_type='application/json',
)
filtered_taxons = filter_by_collection(taxons, request.specify_collection)
result = toJson(list(filtered_taxons))

# SELECT d.TaxonID, COUNT(DISTINCT d.CollectionObjectID), t.ParentID
# FROM determination d
# INNER JOIN taxon t ON t.TaxonID = d.TaxonID
# WHERE d.CollectionMemberID = %s
# AND d.IsCurrent = 1
# GROUP BY d.TaxonId
# ORDER BY d.TaxonId
# """, [request.specify_collection.id])
# result = toJson(cursor.fetchall())
# session = Session()
# query = session.query(
# Determination.TaxonID,
# func.count(distinct(Determination.CollectionObjectID)),
# Taxon.ParentID) \
# .join(Taxon, Determination.TaxonID == Taxon.taxonId) \
# .filter(Determination.collectionMemberId == request.specify_collection.id) \
# .filter(Determination.isCurrent == True) \
# .group_by(Determination.TaxonID).order_by(Determination.TaxonID)

# result = toJson(list(query))
# session.close()
return HttpResponse(result, content_type='application/json')
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('specify', '0048_taxontreedefitem_parent_context_delete'),
]

operations = [
migrations.AddIndex(
model_name='determination',
index=models.Index(
fields=['collectionmemberid', 'iscurrent', 'taxon'],
name='DetColMemCurrentTaxonIDX',
),
),
]
4 changes: 4 additions & 0 deletions specifyweb/specify/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -2888,6 +2888,10 @@ class Meta:
indexes = [
models.Index(fields=['determineddate'], name='DeterminedDateIDX'),
models.Index(fields=['collectionmemberid'], name='DetMemIDX'),
models.Index(
fields=['collectionmemberid', 'iscurrent', 'taxon'],
name='DetColMemCurrentTaxonIDX',
),
models.Index(fields=['alternatename'], name='AlterNameIDX'),
models.Index(fields=['guid'], name='DeterminationGuidIDX'),
models.Index(fields=['typestatusname'], name='TypeStatusNameIDX')
Expand Down
Loading