Skip to content

API v2 phase 3 stories, reprints, and story arcs#716

Open
DeusExTaco wants to merge 9 commits into
GrandComicsDatabase:api-v2from
DeusExTaco:feature/api-v2-phase-3
Open

API v2 phase 3 stories, reprints, and story arcs#716
DeusExTaco wants to merge 9 commits into
GrandComicsDatabase:api-v2from
DeusExTaco:feature/api-v2-phase-3

Conversation

@DeusExTaco

Copy link
Copy Markdown

Summary

  • Add public API v2 endpoints for stories, reprints, and story arcs, plus structured story credit output.
  • Keep the Sprint 3 routes on the public surface only and absent from MYCOMICS routing/schema.
  • Add browse indexes and modified-delta no-count pagination for the heaviest story/reprint list paths.

Validation

  • ruff check apps/api_v2/ apps/gcd/migrations/0072_story_reprint_api_v2_browse_indexes.py
  • ruff format --check apps/api_v2/ apps/gcd/migrations/0072_story_reprint_api_v2_browse_indexes.py
  • python manage.py check
  • python -m pytest apps/api_v2/tests/ -v --tb=short
  • python -m pytest apps/gcd/tests/test_story.py apps/gcd/tests/test_reprint.py -q --tb=short

Manual performance notes

  • Applied migration gcd.0072_story_reprint_api_v2_browse_indexes to the local production-copy Docker DB for measurement.
  • Optimized JSON harness runs: stories list about 306 ms, stories page 5 about 284 ms, stories modified delta about 11 ms.
  • Optimized JSON harness runs: reprints list about 126 ms, reprints page 5 about 90 ms, reprints modified delta about 14 ms.
  • Remaining known slow path: exact count for title__icontains text search.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces new API v2 endpoints, filters, serializers, and tests for stories, reprints, and story arcs, along with database indexes to optimize browsing and delta sync queries. The code review feedback highlights three performance and robustness improvements: resolving a potential N+1 query bottleneck in the story arc serializer by prefetching reprint relations, optimizing database queries in the story viewset by removing an unnecessary SQL JOIN on the character model, and adding a defensive guard check in the feature object serializer to prevent a potential AttributeError when the feature type is null.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread apps/api_v2/serializers/story_arcs.py
Comment thread apps/api_v2/views/stories.py
Comment thread apps/api_v2/serializers/stories.py
@DeusExTaco DeusExTaco marked this pull request as ready for review June 9, 2026 22:32
Comment thread apps/api_v2/filters/stories.py Outdated
lookup_expr='icontains',
)
type = django_filters.NumberFilter(field_name='type_id')
genre = django_filters.CharFilter(field_name='genre')

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

genre can also come from the genres of the feature

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. The v2 filter is only checking Story.genre, but the existing site/search path also treats feature genres as story genre content. I’ll update the filter to include feature_object__genre and cover it with tests.

Comment thread apps/api_v2/serializers/stories.py
"""Serializer metadata for story detail fields."""

fields = StoryListSerializer.Meta.fields + (
'feature_object',

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't existing text credit and character fields also be returned ? The function, but I don't see it being used ?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You’re right. The direct story endpoint currently exposes normalized structured credits/appearances, but it can hide legacy-only text data. I’d like to keep the structured fields and add explicit plain legacy fields so the API stays lossless without mixing object and text shapes. What do you think?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that would be the way to proceed.

for appearance in appearances
]

def get_reprint_origins(self, obj):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you intentionally only returning reprints with known stories ? And no reprints where only the issue is known ?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was intentional in the first pass: those fields only list story-level reprints, while issue-level reprints are represented on /api/v2/reprints/. But I agree the current story detail shape makes that omission too implicit. I think we should either rename these as story-level fields or switch/add object-shaped reprint refs that can include nullable story plus issue data. Thoughts?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both options are valid.
But I think that reprint refs that can include nullable story plus issue data are the way to go, replicating the db and display.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants