refactor(tags): shared tag_query for fandom self-join + serialization (DRY sweep)
The fandom self-join (resolve a character's fandom NAME via Tag.fandom_id->Tag)
and the {id,name,kind,fandom_id,fandom_name} dict were hand-written in
TagService.autocomplete/.list_for_image, GalleryService.get_image_with_tags and
the api/tags handlers — the last few grown by this session's fandom-on-chip
feature. Consolidate to services/tag_query: fandom_join_alias() + tag_columns()
build the select; serialize_tag(row) builds the dict. Now a new tag field is
added in one place.
Over-DRY guard: TagDirectoryService selects the full Tag ORM + an image-count
aggregate (a different select shape) — left as its own variant. §8b: the
fandom_lookup alias lives only in tag_query; gallery + both api/tags handlers
serialize via serialize_tag. Test: serialize_tag handles enum + string kind.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -24,6 +24,7 @@ from sqlalchemy.orm import aliased
|
||||
from ..models import Artist, ImageProvenance, ImageRecord, Post, Source, Tag
|
||||
from ..models.tag import image_tag
|
||||
from .pagination import decode_cursor, encode_cursor
|
||||
from .tag_query import fandom_join_alias, serialize_tag, tag_columns
|
||||
|
||||
# Reserved `platform` filter value selecting images with NO platformed
|
||||
# provenance (filesystem imports). Returned by facets() as a null-valued
|
||||
@@ -543,16 +544,10 @@ class GalleryService:
|
||||
if record is None:
|
||||
return None
|
||||
# Self-join Tag to resolve a character's fandom NAME (not just id) so the
|
||||
# modal chip can label it without an N+1 — mirrors list_for_image.
|
||||
fandom_alias = Tag.__table__.alias("fandom_lookup")
|
||||
# modal chip can label it without an N+1 (shared tag_query helpers).
|
||||
fandom_alias = fandom_join_alias()
|
||||
tag_stmt = (
|
||||
select(
|
||||
Tag.id,
|
||||
Tag.name,
|
||||
Tag.kind,
|
||||
Tag.fandom_id,
|
||||
fandom_alias.c.name.label("fandom_name"),
|
||||
)
|
||||
select(*tag_columns(fandom_alias))
|
||||
.select_from(
|
||||
Tag.__table__
|
||||
.join(image_tag, image_tag.c.tag_id == Tag.id)
|
||||
@@ -599,16 +594,7 @@ class GalleryService:
|
||||
{"id": artist.id, "name": artist.name, "slug": artist.slug}
|
||||
if artist is not None else None
|
||||
),
|
||||
"tags": [
|
||||
{
|
||||
"id": t.id,
|
||||
"name": t.name,
|
||||
"kind": t.kind.value if hasattr(t.kind, "value") else t.kind,
|
||||
"fandom_id": t.fandom_id,
|
||||
"fandom_name": t.fandom_name,
|
||||
}
|
||||
for t in tags
|
||||
],
|
||||
"tags": [serialize_tag(t) for t in tags],
|
||||
"neighbors": neighbors,
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user