diff --git a/store/backend/neurostore/openapi b/store/backend/neurostore/openapi index 667e8b1b..b6c96d4f 160000 --- a/store/backend/neurostore/openapi +++ b/store/backend/neurostore/openapi @@ -1 +1 @@ -Subproject commit 667e8b1be844e230a452d3777ce33e82ed1ef8ca +Subproject commit b6c96d4f699185c2d54778ca67ca5de27e5e5d15 diff --git a/store/backend/neurostore/resources/data.py b/store/backend/neurostore/resources/data.py index 3a59865c..e46bc7e1 100644 --- a/store/backend/neurostore/resources/data.py +++ b/store/backend/neurostore/resources/data.py @@ -1056,6 +1056,7 @@ class BaseStudiesView(ObjectView, ListView): "y": fields.Float(required=False, allow_none=True), "z": fields.Float(required=False, allow_none=True), "radius": fields.Float(required=False, allow_none=True), + **LIST_NESTED_ARGS, } _multi_search = ("name", "description") @@ -1148,7 +1149,51 @@ def eager_load(self, q, args=None): ) # Handle version and user loading - if args.get("info"): + if args.get("nested"): + q = q.options( + selectinload(BaseStudy.versions).options( + selectinload(Study.user) + .load_only(User.name, User.external_id) + .options(raiseload("*", sql_only=True)), + selectinload(Study.tables) + .load_only(Table.id) + .options(raiseload("*", sql_only=True)), + selectinload(Study.analyses).options( + raiseload("*", sql_only=True), + selectinload(Analysis.user) + .load_only(User.name, User.external_id) + .options(raiseload("*", sql_only=True)), + selectinload(Analysis.images).options( + raiseload("*", sql_only=True), + selectinload(Image.user) + .load_only(User.name, User.external_id) + .options(raiseload("*", sql_only=True)), + ), + selectinload(Analysis.points).options( + raiseload("*", sql_only=True), + selectinload(Point.user) + .load_only(User.name, User.external_id) + .options(raiseload("*", sql_only=True)), + selectinload(Point.values).options( + raiseload("*", sql_only=True) + ), + ), + selectinload(Analysis.analysis_conditions).options( + raiseload("*", sql_only=True), + selectinload(AnalysisConditions.condition).options( + raiseload("*", sql_only=True), + selectinload(Condition.user) + .load_only(User.name, User.external_id) + .options(raiseload("*", sql_only=True)), + ), + ), + ), + ), + joinedload(BaseStudy.user) + .load_only(User.name, User.external_id) + .options(raiseload("*", sql_only=True)), + ) + elif args.get("info"): q = q.options( joinedload(BaseStudy.versions).options( raiseload("*", sql_only=True), diff --git a/store/backend/neurostore/tests/api/test_base_studies.py b/store/backend/neurostore/tests/api/test_base_studies.py index 5178b393..bfd38873 100644 --- a/store/backend/neurostore/tests/api/test_base_studies.py +++ b/store/backend/neurostore/tests/api/test_base_studies.py @@ -232,6 +232,24 @@ def test_info_base_study(auth_client, ingest_neurosynth, session): assert isinstance(single_reg_resp.json()["versions"][0], str) +def test_nested_base_study(auth_client, ingest_neurosynth, session): + resp = auth_client.get("/api/base-studies/?nested=true") + assert resp.status_code == 200 + + first_result = resp.json()["results"][0] + first_version = first_result["versions"][0] + + assert isinstance(first_version, dict) + assert "username" in first_version + assert "user" in first_version + + if first_version.get("analyses"): + first_analysis = first_version["analyses"][0] + assert isinstance(first_analysis, dict) + assert "username" in first_analysis + assert "user" in first_analysis + + def test_has_coordinates_images(auth_client, session): # create an empty study doi_a = "abcd"