mirror of
https://github.com/rommapp/romm.git
synced 2026-02-18 00:27:41 +01:00
Merge pull request #2915 from BrandonKowalski/feature/collection-updated-after-query-param
Feature/collection-updated-after-query-param
This commit is contained in:
33
backend/alembic/versions/0065_collections_updated_at_idx.py
Normal file
33
backend/alembic/versions/0065_collections_updated_at_idx.py
Normal file
@@ -0,0 +1,33 @@
|
||||
"""Add indexes on updated_at for collections and smart_collections tables
|
||||
|
||||
Revision ID: 0065_collections_updated_at_idx
|
||||
Revises: 0064_add_updated_at_indexes
|
||||
Create Date: 2026-01-17
|
||||
|
||||
"""
|
||||
|
||||
from alembic import op
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = "0065_collections_updated_at_idx"
|
||||
down_revision = "0064_add_updated_at_indexes"
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade():
|
||||
with op.batch_alter_table("collections", schema=None) as batch_op:
|
||||
batch_op.create_index("ix_collections_updated_at", ["updated_at"], unique=False)
|
||||
|
||||
with op.batch_alter_table("smart_collections", schema=None) as batch_op:
|
||||
batch_op.create_index(
|
||||
"ix_smart_collections_updated_at", ["updated_at"], unique=False
|
||||
)
|
||||
|
||||
|
||||
def downgrade():
|
||||
with op.batch_alter_table("collections", schema=None) as batch_op:
|
||||
batch_op.drop_index("ix_collections_updated_at")
|
||||
|
||||
with op.batch_alter_table("smart_collections", schema=None) as batch_op:
|
||||
batch_op.drop_index("ix_smart_collections_updated_at")
|
||||
@@ -1,9 +1,10 @@
|
||||
import json
|
||||
from datetime import datetime
|
||||
from io import BytesIO
|
||||
from typing import Annotated
|
||||
|
||||
from fastapi import Path as PathVar
|
||||
from fastapi import Request, UploadFile, status
|
||||
from fastapi import Query, Request, UploadFile, status
|
||||
|
||||
from decorators.auth import protected_route
|
||||
from endpoints.responses.collection import (
|
||||
@@ -144,18 +145,26 @@ async def add_smart_collection(
|
||||
|
||||
|
||||
@protected_route(router.get, "", [Scope.COLLECTIONS_READ])
|
||||
def get_collections(request: Request) -> list[CollectionSchema]:
|
||||
def get_collections(
|
||||
request: Request,
|
||||
updated_after: Annotated[
|
||||
datetime | None,
|
||||
Query(
|
||||
description="Filter collections updated after this datetime (ISO 8601 format with timezone information)."
|
||||
),
|
||||
] = None,
|
||||
) -> list[CollectionSchema]:
|
||||
"""Get collections endpoint
|
||||
|
||||
Args:
|
||||
request (Request): Fastapi Request object
|
||||
id (int, optional): Collection id. Defaults to None.
|
||||
updated_after: Filter collections updated after this datetime
|
||||
|
||||
Returns:
|
||||
list[CollectionSchema]: List of collections
|
||||
"""
|
||||
|
||||
collections = db_collection_handler.get_collections()
|
||||
collections = db_collection_handler.get_collections(updated_after=updated_after)
|
||||
|
||||
return CollectionSchema.for_user(request.user.id, [c for c in collections])
|
||||
|
||||
@@ -181,17 +190,28 @@ def get_virtual_collections(
|
||||
|
||||
|
||||
@protected_route(router.get, "/smart", [Scope.COLLECTIONS_READ])
|
||||
def get_smart_collections(request: Request) -> list[SmartCollectionSchema]:
|
||||
def get_smart_collections(
|
||||
request: Request,
|
||||
updated_after: Annotated[
|
||||
datetime | None,
|
||||
Query(
|
||||
description="Filter smart collections updated after this datetime (ISO 8601 format with timezone information)."
|
||||
),
|
||||
] = None,
|
||||
) -> list[SmartCollectionSchema]:
|
||||
"""Get smart collections endpoint
|
||||
|
||||
Args:
|
||||
request (Request): Fastapi Request object
|
||||
updated_after: Filter smart collections updated after this datetime
|
||||
|
||||
Returns:
|
||||
list[SmartCollectionSchema]: List of smart collections
|
||||
"""
|
||||
|
||||
smart_collections = db_collection_handler.get_smart_collections(request.user.id)
|
||||
smart_collections = db_collection_handler.get_smart_collections(
|
||||
request.user.id, updated_after=updated_after
|
||||
)
|
||||
|
||||
return SmartCollectionSchema.for_user(
|
||||
request.user.id, [s for s in smart_collections]
|
||||
@@ -216,7 +236,7 @@ def get_collection(request: Request, id: int) -> CollectionSchema:
|
||||
|
||||
if collection.user_id != request.user.id and not collection.is_public:
|
||||
raise CollectionPermissionError(id)
|
||||
|
||||
|
||||
return CollectionSchema.model_validate(collection)
|
||||
|
||||
|
||||
@@ -414,7 +434,7 @@ async def delete_collection(
|
||||
collection = db_collection_handler.get_collection(id)
|
||||
if not collection:
|
||||
raise CollectionNotFoundInDatabaseException(id)
|
||||
|
||||
|
||||
if collection.user_id != request.user.id:
|
||||
raise CollectionPermissionError(id)
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import functools
|
||||
from collections.abc import Sequence
|
||||
from datetime import datetime
|
||||
from typing import Any
|
||||
|
||||
from sqlalchemy import delete, insert, literal, or_, select, update
|
||||
@@ -85,9 +86,12 @@ class DBCollectionsHandler(DBBaseHandler):
|
||||
@with_roms
|
||||
def get_collections(
|
||||
self,
|
||||
updated_after: datetime | None = None,
|
||||
query: Query = None, # type: ignore
|
||||
session: Session = None, # type: ignore
|
||||
) -> Sequence[Collection]:
|
||||
if updated_after:
|
||||
query = query.filter(Collection.updated_at > updated_after)
|
||||
return session.scalars(query.order_by(Collection.name.asc())).unique().all()
|
||||
|
||||
@begin_session
|
||||
@@ -201,6 +205,7 @@ class DBCollectionsHandler(DBBaseHandler):
|
||||
def get_smart_collections(
|
||||
self,
|
||||
user_id: int | None = None,
|
||||
updated_after: datetime | None = None,
|
||||
session: Session = None, # type: ignore
|
||||
) -> Sequence[SmartCollection]:
|
||||
query = select(SmartCollection).order_by(SmartCollection.name.asc())
|
||||
@@ -211,6 +216,9 @@ class DBCollectionsHandler(DBBaseHandler):
|
||||
(SmartCollection.user_id == user_id) | SmartCollection.is_public
|
||||
)
|
||||
|
||||
if updated_after:
|
||||
query = query.filter(SmartCollection.updated_at > updated_after)
|
||||
|
||||
return session.scalars(query).unique().all()
|
||||
|
||||
@begin_session
|
||||
|
||||
Reference in New Issue
Block a user