Repositories¶
The repository layer lives in website/repositories/ and handles data access only — queries, CRUD, and database interactions.
Repositories:
- Never contain business logic or validation
- Never access Flask context
- Never commit transactions (services own transaction boundaries)
- Inherit from a shared
BaseRepositoryfor common CRUD operations
Overview¶
| Repository | Model | Description |
|---|---|---|
BaseRepository |
— | Generic CRUD operations inherited by all repositories |
ChannelRepository |
Channel |
Discord category management and size tracking |
GameRepository |
Game |
Game queries with filtering, search, pagination, and eager loading |
GameEventRepository |
GameEvent |
Game audit log entry creation |
GameSessionRepository |
GameSession |
Session date range queries and conflict detection |
SpecialEventRepository |
SpecialEvent |
Themed event retrieval with active/inactive filtering |
SystemRepository |
System |
RPG system lookups |
TrophyRepository |
Trophy, UserTrophy |
Achievement data and leaderboard aggregations |
UserRepository |
User |
User entity retrieval |
VttRepository |
Vtt |
Virtual tabletop platform lookups |
API Reference¶
Repository layer for data access operations.
BaseRepository
¶
Bases: Generic[T]
Base repository providing common CRUD operations.
Repositories never commit — they only add, flush, and delete. The service layer owns the transaction boundary.
Source code in website/repositories/base.py
get_by_id(id)
¶
Retrieve an entity by its primary key.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
id
|
int
|
Primary key value. |
required |
Returns:
| Type | Description |
|---|---|
T | None
|
Entity instance, or None if not found. |
get_by_id_or_404(id)
¶
Retrieve an entity by ID or abort with 404.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
id
|
int
|
Primary key value. |
required |
Returns:
| Type | Description |
|---|---|
T
|
Entity instance. |
Raises:
| Type | Description |
|---|---|
NotFound
|
If entity does not exist. |
Source code in website/repositories/base.py
get_all()
¶
Retrieve all entities of this type.
Returns:
| Type | Description |
|---|---|
list[T]
|
List of all entity instances. |
add(entity)
¶
Add an entity to the session and flush.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
entity
|
T
|
Entity instance to persist. |
required |
Returns:
| Type | Description |
|---|---|
T
|
The persisted entity. |
delete(entity)
¶
Delete an entity from the session and flush.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
entity
|
T
|
Entity instance to remove. |
required |
ChannelRepository
¶
Bases: BaseRepository[Channel]
Repository for Channel (Discord category) entities.
Source code in website/repositories/channel.py
get_smallest_by_type(type)
¶
Find the category with the fewest channels for a game type.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
type
|
str
|
Game type (oneshot or campaign). |
required |
Returns:
| Type | Description |
|---|---|
Channel | None
|
Channel with smallest size, or None if no match. |
Source code in website/repositories/channel.py
increment_size(channel)
¶
Increment the channel count of a category.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
channel
|
Channel
|
Channel entity to update. |
required |
GameRepository
¶
Bases: BaseRepository[Game]
Repository for Game entity.
Provides data access methods for games including queries, filtering, and search. All methods return models or None - exceptions for 404s should be raised by services.
Source code in website/repositories/game.py
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 | |
get_by_slug(slug)
¶
Get game by slug.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
slug
|
str
|
URL-safe game identifier. |
required |
Returns:
| Type | Description |
|---|---|
Optional[Game]
|
Game instance or None if not found. |
get_by_slug_or_404(slug)
¶
Get game by slug or raise 404.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
slug
|
str
|
URL-safe game identifier. |
required |
Returns:
| Type | Description |
|---|---|
Game
|
Game instance. |
Raises:
| Type | Description |
|---|---|
NotFound
|
If game with slug doesn't exist. |
Source code in website/repositories/game.py
get_all_slugs()
¶
Get all existing game slugs.
Returns:
| Type | Description |
|---|---|
set[str]
|
Set of all game slugs. |
find_by_gm(gm_id)
¶
Find all games by GM.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
gm_id
|
str
|
GM user ID. |
required |
Returns:
| Type | Description |
|---|---|
list[Game]
|
List of games GMed by this user. |
find_by_player(player_id)
¶
Find all games where user is a player.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
player_id
|
str
|
Player user ID. |
required |
Returns:
| Type | Description |
|---|---|
list[Game]
|
List of games where user is registered as player. |
Source code in website/repositories/game.py
find_by_special_event(event_id)
¶
Find all games for a special event.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
event_id
|
int
|
Special event ID. |
required |
Returns:
| Type | Description |
|---|---|
list[Game]
|
List of games linked to this special event. |
Source code in website/repositories/game.py
query_by_special_event(event_id)
¶
Return a query object for games linked to a special event.
Unlike find_by_special_event (which returns a list), this returns
an unevaluated query suitable for further filtering and pagination.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
event_id
|
int
|
Special event ID. |
required |
Returns:
| Type | Description |
|---|---|
|
SQLAlchemy query filtered by special_event_id. |
Source code in website/repositories/game.py
get_for_update(game_id)
¶
Get game with pessimistic lock for updates.
Uses SELECT FOR UPDATE to prevent race conditions during registration.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
game_id
|
int
|
Game ID to lock. |
required |
Returns:
| Type | Description |
|---|---|
Optional[Game]
|
Game instance with exclusive lock, or None if not found. |
Source code in website/repositories/game.py
get_with_relations(game_id)
¶
Get game with all relationships eagerly loaded.
Prevents N+1 queries by loading gm, system, vtt, players, and sessions.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
game_id
|
int
|
Game ID. |
required |
Returns:
| Type | Description |
|---|---|
Optional[Game]
|
Game instance with relationships loaded, or None if not found. |
Source code in website/repositories/game.py
delete_by_id(game_id)
¶
Delete game by ID.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
game_id
|
int
|
Game ID to delete. |
required |
search(filters, page=1, per_page=20, user_payload=None)
¶
Search games with complex filters and pagination.
Replaces the complex get_filtered_games logic from helpers.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
filters
|
dict
|
Dict containing: - status: List of statuses (open, closed, archived, draft) - game_type: List of types (oneshot, campaign) - restriction: List of restrictions (all, 16+, 18+) - name: Optional name search string - system_id: Optional system ID - vtt_id: Optional VTT ID - gm_id: Optional GM ID (for "my games" views) - player_id: Optional player ID (for "my games as player" views) - special_event_id: Optional special event ID |
required |
page
|
int
|
Page number (1-indexed). |
1
|
per_page
|
int
|
Items per page. |
20
|
user_payload
|
Optional[dict]
|
Optional user auth payload for permission filtering. |
None
|
Returns:
| Type | Description |
|---|---|
tuple[list[Game], int]
|
Tuple of (games list, total count). |
Source code in website/repositories/game.py
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 | |
GameEventRepository
¶
Bases: BaseRepository[GameEvent]
Repository for GameEvent entities.
Source code in website/repositories/game_event.py
log(action, game_id, description=None, user_id=None)
¶
Create and persist a new game event.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
action
|
str
|
Event action type. |
required |
game_id
|
int
|
ID of the related game. |
required |
description
|
str | None
|
Optional event description. |
None
|
user_id
|
str | None
|
Optional ID of the user that performed the action. |
None
|
Returns:
| Type | Description |
|---|---|
GameEvent
|
Created GameEvent instance. |
Source code in website/repositories/game_event.py
GameSessionRepository
¶
Bases: BaseRepository[GameSession]
Repository for GameSession entities.
Source code in website/repositories/game_session.py
find_in_range(start, end)
¶
Find all sessions within a date range.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
start
|
datetime
|
Range start datetime (inclusive). |
required |
end
|
datetime
|
Range end datetime (inclusive). |
required |
Returns:
| Type | Description |
|---|---|
list[GameSession]
|
List of GameSession instances within the range. |
Source code in website/repositories/game_session.py
SpecialEventRepository
¶
Bases: BaseRepository[SpecialEvent]
Repository for SpecialEvent data access.
Handles querying special events with optional filtering by active status.
Source code in website/repositories/special_event.py
get_all(active_only=False)
¶
Get all special events, optionally filtered by active status.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
active_only
|
bool
|
If True, only return active events. Defaults to False. |
False
|
Returns:
| Type | Description |
|---|---|
list[SpecialEvent]
|
List of SpecialEvent instances ordered by name. |
Source code in website/repositories/special_event.py
get_active()
¶
Get all active special events.
Convenience method for getting active events only.
Returns:
| Type | Description |
|---|---|
list[SpecialEvent]
|
List of active SpecialEvent instances ordered by name. |
Source code in website/repositories/special_event.py
get_by_name(name)
¶
Get special event by name.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
Name of the special event. |
required |
Returns:
| Type | Description |
|---|---|
SpecialEvent | None
|
SpecialEvent instance if found, None otherwise. |
Source code in website/repositories/special_event.py
SystemRepository
¶
Bases: BaseRepository[System]
Repository for System entities.
Source code in website/repositories/system.py
get_all_ordered()
¶
Retrieve all systems ordered by name.
Returns:
| Type | Description |
|---|---|
list[System]
|
List of System instances sorted alphabetically. |
TrophyRepository
¶
Bases: BaseRepository[Trophy]
Repository for Trophy data access.
Handles querying trophies, user trophies, and leaderboard aggregations.
Source code in website/repositories/trophy.py
get_user_trophy(user_id, trophy_id)
¶
Get a user's trophy record.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
user_id
|
str
|
User ID. |
required |
trophy_id
|
int
|
Trophy ID. |
required |
Returns:
| Type | Description |
|---|---|
UserTrophy | None
|
UserTrophy instance if user has this trophy, None otherwise. |
Source code in website/repositories/trophy.py
award_trophy(user_id, trophy_id, amount=1)
¶
Create or update a user trophy record.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
user_id
|
str
|
User ID. |
required |
trophy_id
|
int
|
Trophy ID. |
required |
amount
|
int
|
Quantity to add. Defaults to 1. |
1
|
Returns:
| Type | Description |
|---|---|
UserTrophy
|
Created or updated UserTrophy instance. |
Source code in website/repositories/trophy.py
get_leaderboard(trophy_id, limit=10)
¶
Get leaderboard for a specific trophy.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
trophy_id
|
int
|
Trophy ID to get leaderboard for. |
required |
limit
|
int
|
Maximum number of entries to return. Defaults to 10. |
10
|
Returns:
| Type | Description |
|---|---|
list[tuple[User, int]]
|
List of (User, total_quantity) tuples ordered by quantity descending. |
Source code in website/repositories/trophy.py
UserRepository
¶
Bases: BaseRepository[User]
Repository for User entities.
Source code in website/repositories/user.py
get_active_users()
¶
Retrieve all users not marked as inactive.
Returns:
| Type | Description |
|---|---|
list[User]
|
List of User instances where not_player_as_of is NULL. |
get_active_user_ids()
¶
Retrieve IDs of all users not marked as inactive.
Uses a scalar query to avoid loading full ORM objects (and triggering init_on_load).
Returns:
| Type | Description |
|---|---|
list[str]
|
List of user ID strings where not_player_as_of is NULL. |
Source code in website/repositories/user.py
get_inactive_user_ids()
¶
Retrieve IDs of all users marked as inactive.
Uses a scalar query to avoid loading full ORM objects (and triggering init_on_load).
Returns:
| Type | Description |
|---|---|
list[str]
|
List of user ID strings where not_player_as_of is set. |
Source code in website/repositories/user.py
get_by_ids(ids)
¶
Retrieve users by a list of IDs.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ids
|
list[str]
|
List of user ID strings. |
required |
Returns:
| Type | Description |
|---|---|
list[User]
|
List of User instances matching the given IDs. |
Source code in website/repositories/user.py
VttRepository
¶
Bases: BaseRepository[Vtt]
Repository for Vtt entities.
Source code in website/repositories/vtt.py
get_all_ordered()
¶
Retrieve all VTTs ordered by name.
Returns:
| Type | Description |
|---|---|
list[Vtt]
|
List of Vtt instances sorted alphabetically. |