实战指南:动态生成 Inline 与 Reply 键盘)
后端即时通讯API设计【免费下载链接】aiogramaiogram is a modern and fully asynchronous framework for Telegram Bot API written in Python using asyncio项目地址https://gitcode.com/gh_mirrors/ai/aiogram点击查看免费下载导读在 aiogram 3.x 中Telegram 键盘内联键盘与回复键盘不再需要手工拼装list[list[Button]]数据结构而是可以通过aiogram.utils.keyboard提供的KeyboardBuilder系列工具动态生成、调整与合并键盘布局。本文以官方文档 docs/utils/keyboard.rst 为核心结合 keyboard.py 源码 与 测试用例完整讲解InlineKeyboardBuilder与ReplyKeyboardBuilder的用法、参数、底层实现与常见限制读完即可在自己的机器人中按行调整按钮布局、拼接多组按钮并直接发送。一、何时该用 Builder静态 vs 动态KeyboardBuilder的核心价值在于动态生成键盘 markup。官方文档特别提醒docs/utils/keyboard.rst如果你的键盘是静态的、布局固定的最好直接显式定义InlineKeyboardMarkup而不必使用 builder但如果你需要根据运行时的数据动态决定按钮数量和布局就可以放心使用 builder。也就是说静态场景直接构造InlineKeyboardMarkup(inline_keyboard[[...]])或ReplyKeyboardMarkup(keyboard[[...]])更简洁、可读性更高动态场景例如根据数据库中的商品列表、用户选项数量不确定、需要按固定行宽自动换行时builder 能大幅减少手写逻辑。KeyboardBuilder是一个泛型抽象基类源码见 keyboard.py其下有两个具体实现类对应的 Telegram 类型单行最大按钮数max_width按钮总数上限max_buttonsInlineKeyboardBuilderInlineKeyboardMarkup8100ReplyKeyboardBuilderReplyKeyboardMarkup10300这两个上限定义在源码类属性中keyboard.py 与 keyboard.py与 Telegram Bot API 对键盘行数与按钮数的约束保持一致超过会抛出ValueError。二、快速上手生成一个 10 按钮的内联键盘官方文档给出的第一个示例是生成包含 10 个按钮的内联键盘from aiogram.utils.keyboard import InlineKeyboardBuilder builder InlineKeyboardBuilder() for index in range(1, 11): builder.button(textfSet {index}, callback_datafset:{index})要点builder.button(...)每次添加一个按钮内部会构造InlineKeyboardButton并追加到 builder 中源码见 keyboard.pytext是按钮显示的文本callback_data是点击后回传给 Bot 的字符串Telegram 限制为 1-64 字节button()支持几乎所有InlineKeyboardButton字段具体参数见下文第四节。三、调整布局adjust()按行宽重排10 个按钮如果什么都不做默认会被add()按 max_width8 自动换行得到 8 2 两行。若希望“第一行 3 个按钮之后每行 2 个”官方文档给出了adjust用法builder.adjust(3, 2)adjust(*sizes, repeatFalse)的作用是把已添加的所有按钮按指定行宽重新排布源码见 keyboard.py这里修正为 keyboard.py依次使用传入的尺寸当传入尺寸之和小于按钮总数时最后一个尺寸会被复用来填充剩余按钮传repeatTrue时所有尺寸会循环使用不传任何尺寸时等价于adjust(max_width)Inline 为 8Reply 为 10每个尺寸必须是[min_width, max_width]范围内的整数否则抛ValueError。测试用例对此行为做了精确验证tests/test_utils/test_keyboard.py按钮数sizesrepeat结果形状10(3, 2, 1)False[3, 2, 1, 1, 1, 1, 1]12空False[10, 2]Replymax_width1012(3, 2, 1)True[3, 2, 1, 3, 2, 1]源码中repeat_last生成器keyboard.py实现了“最后一个尺寸重复使用”的默认语义repeatTrue则借助itertools.cycle循环全部尺寸。四、合并与拼接attach()与from_markup()动态构建时经常需要把“另一个 builder”或“已生成好的 markup”并入当前 builder。官方文档给出了两种方式4.1 拼接另一个 builderanother_builder InlineKeyboardBuilder(...) # 另一个含按钮的 builder builder.attach(another_builder)attach()源码实现keyboard.py会校验参数必须是KeyboardBuilder实例否则抛ValueError必须与当前 builder 的按钮类型一致——InlineKeyboardBuilder只能 attachInlineKeyboardBuilderReplyKeyboardBuilder只能 attachReplyKeyboardBuilder。官方文档以 warning 明确提示“不能把回复键盘 builder 附加到内联键盘 builder反之亦然”源码中的_button_type类型检查keyboard.py保证了这一点测试用例 test_attach_invalid_button_type 也覆盖了混用会抛ValueError的场景。4.2 拼接已有 markupmarkup InlineKeyboardMarkup(inline_keyboard[...]) # 一些已生成好的 markup builder.attach(InlineKeyboardBuilder.from_markup(markup))from_markup是一个类方法接收InlineKeyboardMarkup或ReplyKeyboardMarkup并把它内部的行结构提取出来作为初始数据源码见 keyboard.py 与 keyboard.pyclassmethod def from_markup(cls, markup): return cls(markupmarkup.inline_keyboard) # 或 markup.keyboard这非常实用当你手上有旧代码生成的静态 markup又想继续用 builder 追加按钮时无需手工解析二维数组。五、导出并发送as_markup()最终把 builder 转成可在消息中使用的 markupawait message.answer(Some text here, reply_markupbuilder.as_markup())as_markup()内部调用export()取出深拷贝的按钮二维数组并构造对应的 markup 对象keyboard.pyInlineKeyboardBuilder.as_markup()返回InlineKeyboardMarkupReplyKeyboardBuilder.as_markup(resize_keyboardTrue, ...)返回ReplyKeyboardMarkup且可以透传is_persistent、resize_keyboard、one_time_keyboard、input_field_placeholder、selective、force_reply等参数这些字段定义见 reply_keyboard_markup.py。需要注意as_markup()不会清空 builder 内部状态多次调用会得到内容相同的 markup而export()每次返回的是深拷贝deepcopy见 keyboard.py测试 test_export 验证了修改导出结果不会影响 builder 内部数据。六、ReplyKeyboardBuilder同样的接口官方文档指出“回复键盘 builder 拥有相同的接口”。示例见仓库中的问答场景 examples/quiz_scene.pymarkup ReplyKeyboardBuilder() markup.add(*[KeyboardButton(textanswer.text) for answer in quiz.answers]) if step 0: markup.button(text Back) markup.button(text Exit) await message.answer( textQUESTIONS[step].text, reply_markupmarkup.adjust(2).as_markup(resize_keyboardTrue), )这里混合使用了三种操作add(*buttons)一次性追加多个已构造好的KeyboardButtonadd会尽量把按钮填入最后一行剩余空位再按 max_width 换新行见 keyboard.pybutton(text...)便捷地构造并添加单个按钮adjust(2)as_markup(resize_keyboardTrue)两列排布并导出同时让 Telegram 客户端按需缩放键盘高度。ReplyKeyboardBuilder.button()的专属参数源码 keyboard.py对应 KeyboardButton 字段参数类型说明textstr必填按钮文本未使用其他特殊字段时点击会直接把文本作为消息发送icon_custom_emoji_idstr \| None按钮文本前显示的自定义 emoji IDstylestr \| None按钮样式danger红/success绿/primary蓝request_usersKeyboardButtonRequestUsers \| None点击后弹出用户选择器仅私聊request_chatKeyboardButtonRequestChat \| None点击后弹出聊天选择器仅私聊request_contactbool \| None请求用户电话号码仅私聊request_locationbool \| None请求用户当前位置仅私聊request_pollKeyboardButtonPollType \| None请求用户创建并发送投票仅私聊web_appWebAppInfo \| None点击后启动 Web App仅私聊七、InlineKeyboardBuilder.button() 参数全解官方文档通过 autoclass 声明的button()方法签名docs/utils/keyboard.rst在源码中已扩展为更完整的参数列表keyboard.py对应 InlineKeyboardButton 的所有字段参数类型说明textstr必填按钮标签文本icon_custom_emoji_idstr \| None文本前的自定义 emojistylestr \| None按钮颜色样式同上urlstr \| None打开的外部 HTTP(S) 或tg://链接callback_datastr \| CallbackData \| None回传数据1-64 字节也接受CallbackData实例web_appWebAppInfo \| None启动 Web App仅私聊login_urlLoginUrl \| NoneTelegram 登录小部件式的授权链接switch_inline_querystr \| None切换到选中的聊天并插入内联查询switch_inline_query_current_chatstr \| None在当前聊天输入框插入内联查询switch_inline_query_chosen_chatSwitchInlineQueryChosenChat \| None按类型选择聊天后插入内联查询copy_textCopyTextButton \| None点击复制指定文本到剪贴板callback_gameCallbackGame \| None启动 HTML5 游戏paybool \| None设为True显示支付按钮⭐与XTR会被替换为 Star 图标其中url、callback_data、web_app、login_url、switch_inline_query*、copy_text、callback_game、pay这些字段互斥——Telegram 要求一个按钮除text、icon_custom_emoji_id、style外只能指定一种行为类型见 inline_keyboard_button.py 的类文档。7.1 与 CallbackData 工厂的集成callback_data参数除了接收原始字符串还可以直接传入CallbackData实例。底层_button()方法会检测到CallbackData类型并自动调用其pack()方法生成回调字符串keyboard.pydef _button(self, **kwargs): if isinstance(callback_data : kwargs.get(callback_data), CallbackData): kwargs[callback_data] callback_data.pack() button self._button_type(**kwargs) return self.add(button)CallbackData的工厂机制定义在 callback_data.py子类需声明prefix字段会按声明顺序以:分隔拼装并强制校验最终长度不超过 64 字节。官方文档 callback_data.rst 给出了完整配合示例class AdminAction(CallbackData, prefixadm): action: Action # 字符串枚举 chat_id: int user_id: int # 在处理器内部 builder InlineKeyboardBuilder() for action in Action: builder.button( textaction.value.title(), callback_dataAdminAction(actionaction, chat_idchat_id, user_iduser_id), ) await bot.send_message(admins_chat, f..., reply_markupbuilder.as_markup())之后用AdminAction.filter(F.action Action.ban)过滤器即可精准命中对应回调测试 test_button 验证了callback_dataMyCallback(valuetest)会被打包为字符串test:test存入按钮。八、其他常用方法buttons、copy、export、rowbuttons属性以生成器形式展平所有按钮keyboard.py常用于遍历或统计按钮总数for btn in builder.buttons: print(btn.text)copy()返回一个与当前 builder 内容完全相同的新实例深拷贝用于在不污染原 builder 的前提下继续调整源码 keyboard.py。测试 test_copy 验证了两个副本相互独立对副本执行add/row不会影响原 builder。export()返回深拷贝的list[list[Button]]可手工交给InlineKeyboardMarkup/ReplyKeyboardMarkup构造keyboard.pymarkup InlineKeyboardMarkup(inline_keyboardbuilder.export())row(*buttons, widthNone)显式添加一整行按钮行宽默认取max_width也可用width参数指定。当传入按钮超过行宽时会自动拆成多行keyboard.py。与adjust的区别在于row是“边构建边定行”adjust是“先全部添加、最后统一重排”。九、底层实现原理与数据校验KeyboardBuilder在构造时即对 markup 结构做严格校验keyboard.pybutton_type必须是InlineKeyboardButton或KeyboardButton的子类否则抛ValueError初始 markup 必须是list[list[Button]]每行长度不得超过max_width按钮总数不得超过max_buttons否则抛ValueError对应_validate_row/_validate_markup见 keyboard.pyadjust/row的行宽必须落在[min_width, max_width]区间内且为整数_validate_size见 keyboard.py。这些校验在 tests/test_utils/test_keyboard.py 中都有对应用例非法的按钮类型、超长的行、超量的按钮总数、非整数行宽等都会抛出ValueError保证最终生成的 markup 一定符合 Telegram API 的约束。十、注意事项小结静态优先布局固定的键盘直接写InlineKeyboardMarkup/ReplyKeyboardMarkup动态内容再使用 builder类型不可混搭attach()只允许同类型 builder 互相拼接内联与回复键盘互不兼容keyboard.py行宽与总数上限Inline 每行最多 8 个、总数最多 100Reply 每行最多 10 个、总数最多 300违反会抛ValueErroradjust的尾部复用规则默认最后一个尺寸重复使用repeatTrue才循环全部尺寸export()返回深拷贝可以放心修改导出结果而不影响 builder 内部状态。结语InlineKeyboardBuilder与ReplyKeyboardBuilder是 aiogram 3.x 处理动态键盘的标准工具button()负责便捷地造按钮add/row/adjust负责布局attach/from_markup负责合并as_markup()负责交付给消息发送接口。配合CallbackData工厂还可以获得类型安全的回调数据链路。更多 API 细节可查阅 keyboard.py 源码、官方文档 docs/utils/keyboard.rst 以及完整的 test_keyboard.py 测试套件。赞分享后端即时通讯API设计【免费下载链接】aiogramaiogram is a modern and fully asynchronous framework for Telegram Bot API written in Python using asyncio项目地址https://gitcode.com/gh_mirrors/ai/aiogram点击查看免费下载相关推荐探秘Apache MINA构建高效可扩展网络应用的利器探秘Apache MINA构建高效可扩展网络应用的利器 在当今瞬息万变的互联网世界中寻找一款既能保证高性能又能支持高可扩展性的网络应用框架成为开发者们的一大后端即时通讯API设计aiogram 内联键盘 InlineKeyboardMarkup 完全指南数据结构、按钮类型与动态构建器实战aiogram 内联键盘 InlineKeyboardMarkup 完全指南数据结构、按钮类型与动态构建器实战 本文以 aiogram 3.x 仓库中 Inl后端即时通讯API设计Flowbite KBDKeyboard键盘按键组件实战指南用 Tailwind CSS 快速构建键位提示 UIFlowbite KBDKeyboard键盘按键组件实战指南用 Tailwind CSS 快速构建键位提示 UI KBDKeyboard是 FlowbUI组件前端创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考