如何在Aiogram中传入数据进入Scene场景?
解决Aiogram Scene传参时的AttributeError问题
你遇到的AttributeError: 'str' object has no attribute 'scene',是因为直接实例化Scene子类并传入参数后,错误地将实例(或传入的字符串)当成handler注册,打破了aiogram内部的场景初始化逻辑——aiogram要求通过as_handler()类方法生成标准handler对象,而非直接传实例。
下面提供两种可行的传参方案:
方案一:通过as_handler()的kwargs传递参数
先修改Scene子类,添加__init__方法接收参数:
class QuizScene(Scene, state="quiz"): def __init__(self, quiz_topic: str, **kwargs): super().__init__(**kwargs) self.quiz_topic = quiz_topic # 保存传入的字符串参数 async def on_enter(self, event: Message) -> None: # 在场景内使用传入的参数 await event.answer(f"欢迎来到{self.quiz_topic}答题环节!")
注册场景时,通过as_handler()的关键字参数传递数据:
quiz_router = Router(name=__name__) # 将参数通过as_handler的kwargs传入Scene的__init__ quiz_router.message.register(QuizScene.as_handler(quiz_topic="Python基础"), Command("quiz"))
方案二:使用上下文存储传递动态参数
如果参数需要从用户触发命令的上下文获取(比如/quiz Python进阶中的主题),可以先把数据存入上下文,再启动场景:
async def start_quiz_handler(message: Message, state: FSMContext): # 从命令文本中提取参数 quiz_topic = message.text.split(maxsplit=1)[1] if len(message.text.split())>1 else "默认主题" # 将参数存入上下文 await state.update_data(quiz_topic=quiz_topic) # 启动场景 await QuizScene.as_handler()(message, state) quiz_router.message.register(start_quiz_handler, Command("quiz"))
然后在Scene类中读取上下文数据:
class QuizScene(Scene, state="quiz"): async def on_enter(self, event: Message, state: FSMContext) -> None: data = await state.get_data() quiz_topic = data.get("quiz_topic", "默认主题") await event.answer(f"欢迎来到{quiz_topic}答题环节!")
关键注意点
永远不要直接实例化Scene子类(比如QuizScene("Python基础"))并传给register方法,必须通过as_handler()生成合法的handler对象,所有场景参数要么通过该方法的kwargs传入,要么通过上下文存储传递。
内容的提问来源于stack exchange,提问作者tonyfarmer
相关产品推荐
相关产品推荐

