mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-09-06 16:07:01 +08:00
refactor: govern background tasks and query ownership
This commit is contained in:
+50
-11
@@ -3,6 +3,7 @@ from typing import Optional, Union
|
||||
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from sqlalchemy.orm import Session
|
||||
from sqlalchemy import and_, or_, select
|
||||
|
||||
from app.db.base import DbOper
|
||||
from app.db.models.message import Message
|
||||
@@ -105,7 +106,14 @@ class MessageOper(DbOper):
|
||||
"""
|
||||
分页获取消息记录。
|
||||
"""
|
||||
return Message.list_by_page(self._db, page, count)
|
||||
return self._execute_sync_query(
|
||||
lambda session: list(session.execute(
|
||||
select(Message)
|
||||
.order_by(Message.reg_time.desc(), Message.id.desc())
|
||||
.offset((page - 1) * count)
|
||||
.limit(count)
|
||||
).scalars().all())
|
||||
)
|
||||
|
||||
def exists_by_source(self, source: str) -> bool:
|
||||
"""
|
||||
@@ -114,7 +122,11 @@ class MessageOper(DbOper):
|
||||
:param source: 消息来源唯一标识
|
||||
:return: 是否存在匹配记录
|
||||
"""
|
||||
return Message.exists_by_source(self._db, source)
|
||||
return self._execute_sync_query(
|
||||
lambda session: session.execute(
|
||||
select(Message.id).where(Message.source == source).limit(1)
|
||||
).scalars().first() is not None
|
||||
)
|
||||
|
||||
async def async_list_by_page(
|
||||
self, page: int = 1, count: int = 30
|
||||
@@ -122,7 +134,17 @@ class MessageOper(DbOper):
|
||||
"""
|
||||
分页获取消息记录。
|
||||
"""
|
||||
return await Message.async_list_by_page(self._db, page, count)
|
||||
async def query(session: AsyncSession) -> list[Message]:
|
||||
"""在调用方异步会话中执行消息分页查询。"""
|
||||
result = await session.execute(
|
||||
select(Message)
|
||||
.order_by(Message.reg_time.desc(), Message.id.desc())
|
||||
.offset((page - 1) * count)
|
||||
.limit(count)
|
||||
)
|
||||
return list(result.scalars().all())
|
||||
|
||||
return await self._execute_async_query(query)
|
||||
|
||||
async def async_list_sent_by_page(
|
||||
self,
|
||||
@@ -135,11 +157,28 @@ class MessageOper(DbOper):
|
||||
"""
|
||||
分页获取系统发送的通知消息。
|
||||
"""
|
||||
return await Message.async_list_sent_by_page(
|
||||
self._db,
|
||||
page,
|
||||
count,
|
||||
all_clear_before=all_clear_before,
|
||||
system_clear_before=system_clear_before,
|
||||
media_clear_before=media_clear_before,
|
||||
)
|
||||
async def query(session: AsyncSession) -> list[Message]:
|
||||
"""在调用方异步会话中执行通知消息分页查询。"""
|
||||
statement = select(Message).where(Message.action == 1)
|
||||
if all_clear_before:
|
||||
statement = statement.where(Message.reg_time > all_clear_before)
|
||||
if system_clear_before:
|
||||
statement = statement.where(or_(
|
||||
and_(Message.image.isnot(None), Message.image != ""),
|
||||
Message.reg_time > system_clear_before,
|
||||
))
|
||||
if media_clear_before:
|
||||
statement = statement.where(or_(
|
||||
Message.image.is_(None),
|
||||
Message.image == "",
|
||||
Message.reg_time > media_clear_before,
|
||||
))
|
||||
result = await session.execute(
|
||||
statement
|
||||
.order_by(Message.reg_time.desc(), Message.id.desc())
|
||||
.offset((page - 1) * count)
|
||||
.limit(count)
|
||||
)
|
||||
return list(result.scalars().all())
|
||||
|
||||
return await self._execute_async_query(query)
|
||||
|
||||
+86
-18
@@ -1,7 +1,8 @@
|
||||
from datetime import datetime
|
||||
from typing import Any, List, Mapping, Tuple, Optional
|
||||
|
||||
from sqlalchemy import delete as sqlalchemy_delete
|
||||
from sqlalchemy import delete as sqlalchemy_delete, select
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from app.db.base import DbOper
|
||||
@@ -11,6 +12,18 @@ from app.db.models.sitestatistic import SiteStatistic
|
||||
from app.db.models.siteuserdata import SiteUserData
|
||||
|
||||
|
||||
async def _async_first(session: AsyncSession, statement: Any) -> Optional[Site]:
|
||||
"""执行异步站点查询并返回首条记录。"""
|
||||
result = await session.execute(statement)
|
||||
return result.scalars().first()
|
||||
|
||||
|
||||
async def _async_all(session: AsyncSession, statement: Any) -> list[Site]:
|
||||
"""执行异步站点查询并返回稳定列表。"""
|
||||
result = await session.execute(statement)
|
||||
return list(result.scalars().all())
|
||||
|
||||
|
||||
class SiteOper(DbOper):
|
||||
"""
|
||||
站点管理
|
||||
@@ -21,7 +34,7 @@ class SiteOper(DbOper):
|
||||
新增站点
|
||||
"""
|
||||
site = Site(**kwargs)
|
||||
if not site.get_by_domain(self._db, kwargs.get("domain")):
|
||||
if not self.get_by_domain(kwargs.get("domain")):
|
||||
self._stage_create(site)
|
||||
return True, "新增站点成功"
|
||||
return False, "站点已存在"
|
||||
@@ -30,13 +43,22 @@ class SiteOper(DbOper):
|
||||
"""
|
||||
查询单个站点
|
||||
"""
|
||||
return Site.get(self._db, sid)
|
||||
return self._execute_sync_query(
|
||||
lambda session: session.execute(
|
||||
select(Site).where(Site.id == sid)
|
||||
).scalars().first()
|
||||
)
|
||||
|
||||
async def async_get(self, sid: int) -> Optional[Site]:
|
||||
"""
|
||||
异步查询单个站点
|
||||
"""
|
||||
return await Site.async_get(self._db, sid)
|
||||
return await self._execute_async_query(
|
||||
lambda session: _async_first(
|
||||
session,
|
||||
select(Site).where(Site.id == sid),
|
||||
)
|
||||
)
|
||||
|
||||
async def get_by_id(self, site_id: int) -> Optional[Site]:
|
||||
"""读取站点写用例需要的目标站点。"""
|
||||
@@ -80,35 +102,59 @@ class SiteOper(DbOper):
|
||||
"""
|
||||
获取站点列表
|
||||
"""
|
||||
return Site.list(self._db)
|
||||
return self._execute_sync_query(
|
||||
lambda session: list(session.execute(select(Site)).scalars().all())
|
||||
)
|
||||
|
||||
async def async_list(self) -> List[Site]:
|
||||
"""
|
||||
异步获取站点列表
|
||||
"""
|
||||
return await Site.async_list(self._db)
|
||||
return await self._execute_async_query(
|
||||
lambda session: _async_all(session, select(Site))
|
||||
)
|
||||
|
||||
async def async_list_order_by_pri(self) -> List[Site]:
|
||||
"""异步按优先级获取站点,供站点查询应用服务使用。"""
|
||||
return await Site.async_list_order_by_pri(self._db)
|
||||
return await self._execute_async_query(
|
||||
lambda session: _async_all(
|
||||
session,
|
||||
select(Site).order_by(Site.pri),
|
||||
)
|
||||
)
|
||||
|
||||
def list_order_by_pri(self) -> List[Site]:
|
||||
"""
|
||||
获取站点列表
|
||||
"""
|
||||
return Site.list_order_by_pri(self._db)
|
||||
return self._execute_sync_query(
|
||||
lambda session: list(
|
||||
session.execute(select(Site).order_by(Site.pri)).scalars().all()
|
||||
)
|
||||
)
|
||||
|
||||
def list_active(self) -> List[Site]:
|
||||
"""
|
||||
按状态获取站点列表
|
||||
"""
|
||||
return Site.get_actives(self._db)
|
||||
return self._execute_sync_query(
|
||||
lambda session: list(
|
||||
session.execute(
|
||||
select(Site).where(Site.is_active.is_(True))
|
||||
).scalars().all()
|
||||
)
|
||||
)
|
||||
|
||||
async def async_list_active(self) -> List[Site]:
|
||||
"""
|
||||
异步按状态获取站点列表
|
||||
"""
|
||||
return await Site.async_get_actives(self._db)
|
||||
return await self._execute_async_query(
|
||||
lambda session: _async_all(
|
||||
session,
|
||||
select(Site).where(Site.is_active.is_(True)),
|
||||
)
|
||||
)
|
||||
|
||||
def delete(self, sid: int):
|
||||
"""
|
||||
@@ -128,7 +174,7 @@ class SiteOper(DbOper):
|
||||
"""
|
||||
更新站点
|
||||
"""
|
||||
site = Site.get(self._db, sid)
|
||||
site = self.get(sid)
|
||||
if not site:
|
||||
return None
|
||||
self._stage_update(site, payload)
|
||||
@@ -147,37 +193,59 @@ class SiteOper(DbOper):
|
||||
"""
|
||||
按域名获取站点
|
||||
"""
|
||||
return Site.get_by_domain(self._db, domain)
|
||||
return self._execute_sync_query(
|
||||
lambda session: session.execute(
|
||||
select(Site).where(Site.domain == domain)
|
||||
).scalars().first()
|
||||
)
|
||||
|
||||
async def async_get_by_domain(self, domain: str) -> Optional[Site]:
|
||||
"""
|
||||
异步按域名获取站点
|
||||
"""
|
||||
return await Site.async_get_by_domain(self._db, domain)
|
||||
return await self._execute_async_query(
|
||||
lambda session: _async_first(
|
||||
session,
|
||||
select(Site).where(Site.domain == domain),
|
||||
)
|
||||
)
|
||||
|
||||
async def async_get_by_name(self, name: str) -> Optional[Site]:
|
||||
"""
|
||||
异步按名称获取站点
|
||||
"""
|
||||
return await Site.async_get_by_name(self._db, name)
|
||||
return await self._execute_async_query(
|
||||
lambda session: _async_first(
|
||||
session,
|
||||
select(Site).where(Site.name == name),
|
||||
)
|
||||
)
|
||||
|
||||
def get_domains_by_ids(self, ids: List[int]) -> List[Optional[str]]:
|
||||
"""
|
||||
按ID获取站点域名
|
||||
"""
|
||||
return Site.get_domains_by_ids(self._db, ids)
|
||||
if not ids:
|
||||
return []
|
||||
return self._execute_sync_query(
|
||||
lambda session: list(
|
||||
session.execute(
|
||||
select(Site.domain).where(Site.id.in_(ids))
|
||||
).scalars().all()
|
||||
)
|
||||
)
|
||||
|
||||
def exists(self, domain: str) -> bool:
|
||||
"""
|
||||
判断站点是否存在
|
||||
"""
|
||||
return Site.get_by_domain(self._db, domain) is not None
|
||||
return self.get_by_domain(domain) is not None
|
||||
|
||||
def update_cookie(self, domain: str, cookies: str) -> Tuple[bool, str]:
|
||||
"""
|
||||
更新站点Cookie
|
||||
"""
|
||||
site = Site.get_by_domain(self._db, domain)
|
||||
site = self.get_by_domain(domain)
|
||||
if not site:
|
||||
return False, "站点不存在"
|
||||
self._stage_update(site, {
|
||||
@@ -189,7 +257,7 @@ class SiteOper(DbOper):
|
||||
"""
|
||||
更新站点rss
|
||||
"""
|
||||
site = Site.get_by_domain(self._db, domain)
|
||||
site = self.get_by_domain(domain)
|
||||
if not site:
|
||||
return False, "站点不存在"
|
||||
self._stage_update(site, {
|
||||
|
||||
+127
-47
@@ -297,13 +297,24 @@ class SubscribeOper(DbOper):
|
||||
"""
|
||||
获取订阅
|
||||
"""
|
||||
return Subscribe.get(self._db, rid=sid)
|
||||
return self._execute_sync_query(
|
||||
lambda session: session.execute(
|
||||
select(Subscribe).where(Subscribe.id == sid)
|
||||
).scalars().first()
|
||||
)
|
||||
|
||||
async def async_get(self, sid: int) -> Optional[Subscribe]:
|
||||
"""
|
||||
获取订阅
|
||||
"""
|
||||
return await Subscribe.async_get(self._db, rid=sid)
|
||||
if self._db is not None and not isinstance(self._db, (Session, AsyncSession)):
|
||||
# 保留旧测试替身与插件注入对象对 Model ABI 的兼容入口。
|
||||
return await Subscribe.async_get(self._db, rid=sid)
|
||||
async def query(session: AsyncSession) -> Optional[Subscribe]:
|
||||
"""在调用方异步会话中执行订阅主键查询。"""
|
||||
result = await session.execute(select(Subscribe).where(Subscribe.id == sid))
|
||||
return result.scalars().first()
|
||||
return await self._execute_async_query(query)
|
||||
|
||||
async def async_list_by_media_identity(
|
||||
self,
|
||||
@@ -312,12 +323,18 @@ class SubscribeOper(DbOper):
|
||||
music_type: Optional[str] = None,
|
||||
) -> List[Subscribe]:
|
||||
"""异步按规范媒体身份读取订阅。"""
|
||||
return await Subscribe.async_list_by_media_identity(
|
||||
self._db,
|
||||
media_source=media_source,
|
||||
media_id=media_id,
|
||||
music_type=music_type,
|
||||
)
|
||||
async def query(session: AsyncSession) -> List[Subscribe]:
|
||||
"""在调用方异步会话中执行媒体身份列表查询。"""
|
||||
condition = Subscribe._identity_condition( # pylint: disable=protected-access
|
||||
media_source, media_id, music_type
|
||||
)
|
||||
if condition is None:
|
||||
return []
|
||||
result = await session.execute(select(Subscribe).where(condition))
|
||||
return list(result.scalars().all())
|
||||
if isinstance(self._db, AsyncSession):
|
||||
return await query(self._db)
|
||||
return await self._execute_async_query(query)
|
||||
|
||||
def list_by_media_identity(
|
||||
self,
|
||||
@@ -326,12 +343,15 @@ class SubscribeOper(DbOper):
|
||||
music_type: Optional[str] = None,
|
||||
) -> List[Subscribe]:
|
||||
"""同步按规范媒体身份读取订阅。"""
|
||||
return Subscribe.list_by_media_identity(
|
||||
self._db,
|
||||
media_source=media_source,
|
||||
media_id=media_id,
|
||||
music_type=music_type,
|
||||
)
|
||||
def query(session: Session) -> List[Subscribe]:
|
||||
"""在调用方同步会话中执行媒体身份列表查询。"""
|
||||
condition = Subscribe._identity_condition( # pylint: disable=protected-access
|
||||
media_source, media_id, music_type
|
||||
)
|
||||
if condition is None:
|
||||
return []
|
||||
return list(session.execute(select(Subscribe).where(condition)).scalars().all())
|
||||
return self._execute_sync_query(query)
|
||||
|
||||
async def get_candidate(
|
||||
self,
|
||||
@@ -360,11 +380,8 @@ class SubscribeOper(DbOper):
|
||||
music_type: Optional[str],
|
||||
) -> List[SubscribeDeletionCandidate]:
|
||||
"""按媒体身份读取去重后的订阅删除快照。"""
|
||||
subscribes = await Subscribe.async_list_by_media_identity(
|
||||
self._db,
|
||||
media_source=media_source,
|
||||
media_id=media_id,
|
||||
music_type=music_type,
|
||||
subscribes = await self.async_list_by_media_identity(
|
||||
media_source, media_id, music_type
|
||||
)
|
||||
candidates = []
|
||||
seen_ids = set()
|
||||
@@ -395,11 +412,7 @@ class SubscribeOper(DbOper):
|
||||
|
||||
async def list_search_ids(self, username: str, state: str) -> List[int]:
|
||||
"""返回用户指定状态的订阅编号,不向应用用例暴露 ORM 列表。"""
|
||||
subscribes = await Subscribe.async_list_by_username(
|
||||
self._db,
|
||||
username,
|
||||
state=state,
|
||||
)
|
||||
subscribes = await self.async_list_by_username(username, state=state)
|
||||
return [subscribe.id for subscribe in subscribes if subscribe.id]
|
||||
|
||||
def get_by(
|
||||
@@ -410,9 +423,18 @@ class SubscribeOper(DbOper):
|
||||
"""
|
||||
根据条件查询订阅
|
||||
"""
|
||||
return Subscribe.get_by(
|
||||
self._db, type, media_source, media_id, season, music_type,
|
||||
)
|
||||
def query(session: Session) -> Optional[Subscribe]:
|
||||
"""在调用方同步会话中执行类型媒体查询。"""
|
||||
condition = Subscribe._identity_condition( # pylint: disable=protected-access
|
||||
media_source, media_id, music_type
|
||||
)
|
||||
if condition is None:
|
||||
return None
|
||||
statement = select(Subscribe).where(condition, Subscribe.type == type)
|
||||
if season is not None:
|
||||
statement = statement.where(Subscribe.season == season)
|
||||
return session.execute(statement).scalars().first()
|
||||
return self._execute_sync_query(query)
|
||||
|
||||
async def async_get_by(
|
||||
self, type: str, media_source: MediaSource, media_id: str,
|
||||
@@ -422,25 +444,55 @@ class SubscribeOper(DbOper):
|
||||
"""
|
||||
根据条件查询订阅
|
||||
"""
|
||||
return await Subscribe.async_get_by(
|
||||
self._db, type, media_source, media_id, season, music_type,
|
||||
)
|
||||
async def query(session: AsyncSession) -> Optional[Subscribe]:
|
||||
"""在调用方异步会话中执行类型媒体查询。"""
|
||||
condition = Subscribe._identity_condition( # pylint: disable=protected-access
|
||||
media_source, media_id, music_type
|
||||
)
|
||||
if condition is None:
|
||||
return None
|
||||
statement = select(Subscribe).where(condition, Subscribe.type == type)
|
||||
if season is not None:
|
||||
statement = statement.where(Subscribe.season == season)
|
||||
result = await session.execute(statement)
|
||||
return result.scalars().first()
|
||||
return await self._execute_async_query(query)
|
||||
|
||||
def list(self, state: Optional[str] = None) -> List[Subscribe]:
|
||||
"""
|
||||
获取订阅列表
|
||||
"""
|
||||
if state:
|
||||
return Subscribe.get_by_state(self._db, state)
|
||||
return Subscribe.list(self._db)
|
||||
return self._execute_sync_query(
|
||||
lambda session: list(session.execute(
|
||||
select(Subscribe).where(Subscribe.state.in_(state.split(',')))
|
||||
).scalars().all())
|
||||
)
|
||||
return self._execute_sync_query(
|
||||
lambda session: list(session.execute(select(Subscribe)).scalars().all())
|
||||
)
|
||||
|
||||
async def async_list(self, state: Optional[str] = None) -> List[Subscribe]:
|
||||
"""
|
||||
异步获取订阅列表
|
||||
"""
|
||||
if self._db is not None and not isinstance(self._db, (Session, AsyncSession)):
|
||||
if state:
|
||||
return await Subscribe.async_get_by_state(self._db, state)
|
||||
return await Subscribe.async_list(self._db)
|
||||
if state:
|
||||
return await Subscribe.async_get_by_state(self._db, state)
|
||||
return await Subscribe.async_list(self._db)
|
||||
async def query(session: AsyncSession) -> List[Subscribe]:
|
||||
"""在调用方异步会话中执行状态列表查询。"""
|
||||
result = await session.execute(
|
||||
select(Subscribe).where(Subscribe.state.in_(state.split(',')))
|
||||
)
|
||||
return list(result.scalars().all())
|
||||
return await self._execute_async_query(query)
|
||||
async def query_all(session: AsyncSession) -> List[Subscribe]:
|
||||
"""在调用方异步会话中执行全量订阅查询。"""
|
||||
result = await session.execute(select(Subscribe))
|
||||
return list(result.scalars().all())
|
||||
return await self._execute_async_query(query_all)
|
||||
|
||||
async def async_list_by_username(
|
||||
self,
|
||||
@@ -449,12 +501,20 @@ class SubscribeOper(DbOper):
|
||||
mtype: Optional[str] = None,
|
||||
) -> List[Subscribe]:
|
||||
"""异步按用户获取订阅。"""
|
||||
return await Subscribe.async_list_by_username(
|
||||
self._db,
|
||||
username=username,
|
||||
state=state,
|
||||
mtype=mtype,
|
||||
)
|
||||
if self._db is not None and not isinstance(self._db, (Session, AsyncSession)):
|
||||
return await Subscribe.async_list_by_username(
|
||||
self._db, username=username, state=state, mtype=mtype
|
||||
)
|
||||
async def query(session: AsyncSession) -> List[Subscribe]:
|
||||
"""在调用方异步会话中执行用户筛选查询。"""
|
||||
statement = select(Subscribe).where(Subscribe.username == username)
|
||||
if state:
|
||||
statement = statement.where(Subscribe.state == state)
|
||||
if mtype:
|
||||
statement = statement.where(Subscribe.type == mtype)
|
||||
result = await session.execute(statement)
|
||||
return list(result.scalars().all())
|
||||
return await self._execute_async_query(query)
|
||||
|
||||
async def async_list_by_title(
|
||||
self,
|
||||
@@ -462,11 +522,14 @@ class SubscribeOper(DbOper):
|
||||
season: Optional[int] = None,
|
||||
) -> List[Subscribe]:
|
||||
"""异步按标题获取订阅,供旧查询测试和迁移调用兼容。"""
|
||||
return await Subscribe.async_list_by_title(
|
||||
self._db,
|
||||
title=title,
|
||||
season=season,
|
||||
)
|
||||
async def query(session: AsyncSession) -> List[Subscribe]:
|
||||
"""在调用方异步会话中执行标题列表查询。"""
|
||||
statement = select(Subscribe).where(Subscribe.name == title)
|
||||
if season is not None:
|
||||
statement = statement.where(Subscribe.season == season)
|
||||
result = await session.execute(statement)
|
||||
return list(result.scalars().all())
|
||||
return await self._execute_async_query(query)
|
||||
|
||||
def delete(self, sid: int):
|
||||
"""
|
||||
@@ -535,13 +598,30 @@ class SubscribeOper(DbOper):
|
||||
"""
|
||||
获取指定用户的订阅
|
||||
"""
|
||||
return Subscribe.list_by_username(self._db, username=username, state=state, mtype=mtype)
|
||||
def query(session: Session) -> List[Subscribe]:
|
||||
"""在调用方同步会话中执行用户筛选查询。"""
|
||||
statement = select(Subscribe).where(Subscribe.username == username)
|
||||
if state:
|
||||
statement = statement.where(Subscribe.state == state)
|
||||
if mtype:
|
||||
statement = statement.where(Subscribe.type == mtype)
|
||||
return list(session.execute(statement).scalars().all())
|
||||
return self._execute_sync_query(query)
|
||||
|
||||
def list_by_type(self, mtype: str, days: int = 7) -> List[Subscribe]:
|
||||
"""
|
||||
获取指定类型的订阅
|
||||
"""
|
||||
return Subscribe.list_by_type(self._db, mtype=mtype, days=days)
|
||||
def query(session: Session) -> List[Subscribe]:
|
||||
"""在调用方同步会话中执行时间窗订阅查询。"""
|
||||
cutoff = time.strftime(
|
||||
"%Y-%m-%d %H:%M:%S",
|
||||
time.localtime(time.time() - 86400 * int(days)),
|
||||
)
|
||||
return list(session.execute(select(Subscribe).where(
|
||||
Subscribe.type == mtype, Subscribe.date >= cutoff
|
||||
)).scalars().all())
|
||||
return self._execute_sync_query(query)
|
||||
|
||||
def add_history(self, **kwargs):
|
||||
"""
|
||||
|
||||
+13
-2
@@ -12,6 +12,7 @@ runtime 兼容映射指向 SDK 薄门面;canonical 数据访问模块仍只依
|
||||
from typing import List, Optional
|
||||
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from sqlalchemy import select
|
||||
|
||||
from app.db.base import DbOper
|
||||
from app.db.models.user import User
|
||||
@@ -103,13 +104,23 @@ class UserOper(DbOper):
|
||||
"""
|
||||
异步根据用户名获取用户。
|
||||
"""
|
||||
return await User.async_get_by_name(self._db, name)
|
||||
async def query(session: AsyncSession) -> Optional[User]:
|
||||
"""在调用方异步会话中执行用户名查询。"""
|
||||
result = await session.execute(select(User).where(User.name == name))
|
||||
return result.scalars().first()
|
||||
|
||||
return await self._execute_async_query(query)
|
||||
|
||||
async def async_get_by_id(self, user_id: int) -> Optional[User]:
|
||||
"""
|
||||
异步根据用户 ID 获取用户。
|
||||
"""
|
||||
return await User.async_get_by_id(self._db, user_id)
|
||||
async def query(session: AsyncSession) -> Optional[User]:
|
||||
"""在调用方异步会话中执行用户 ID 查询。"""
|
||||
result = await session.execute(select(User).where(User.id == user_id))
|
||||
return result.scalars().first()
|
||||
|
||||
return await self._execute_async_query(query)
|
||||
|
||||
def get_permissions(self, name: str) -> dict:
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user