分类: Discord 机器人开发
Discord 机器人开发#7用模态框(Modal)接收用户输入(Python 示例)
本文译自韩语原文。
目录8 项
大家好!我是 Mojangcam 😎
上一篇我们学习了如何用下拉菜单(Select Menu)把多个选项整齐地收纳起来,对吧?不过按钮也好,下拉菜单也好,说到底都是在预先设定好的选项里做选择。如果需要用户自己自由地输入文字再发送,该怎么办呢?
这一篇我们就来做承担这个角色的模态框(Modal)!模态框就是用户点击命令后,在屏幕中央弹出的弹窗输入框。咨询受理、建议箱、昵称登记、举报表单等等,几乎所有"需要用户亲自输入文字"的地方都会用到它。比起让用户在聊天框里打一长串字要清爽得多,还能一次接收好几个输入框的内容!

📌 准备工作
- Python 3.8 及以上
- discord.py 最新 2.x 版本(模态框从 2.0 开始支持)
- 机器人 Token + 已把机器人邀请进服务器(参考本系列第 1 篇)
pip install -U discord.py查看版本的方法如下:
pip show discord.py显示 Version: 2.x 这样 2.x 及以上就 OK!模态框(Modal)是 discord.py 从 2.0 开始支持的功能,在 1.x 版本中无法运行。
📌 第 1 步 - 创建 Modal 类
模态框的核心是 discord.ui.Modal 类。继承这个类,定义各个输入框(TextInput),再编写用户提交时的行为(on_submit)。
import discord
from discord.ext import commands
class SuggestModal(discord.ui.Modal, title="建议箱 📮"):
# 单行短输入框
subject = discord.ui.TextInput(
label="标题",
placeholder="请输入建议标题",
max_length=50,
)
# 多行长输入框
content = discord.ui.TextInput(
label="内容",
style=discord.TextStyle.long,
placeholder="请自由填写详细内容!",
required=True,
max_length=500,
)
async def on_submit(self, interaction: discord.Interaction):
await interaction.response.send_message(
f"✅ 建议已提交!\n**标题:** {self.subject.value}\n**内容:** {self.content.value}",
ephemeral=True,
)逐个拆解来看 💡
- title:显示在模态框弹窗最上方的大标题。在定义类时像
discord.ui.Modal, title="..."这样传入。 - TextInput:就是一个实际的输入框。声明为类变量后,会按从上到下的顺序显示在屏幕上。(一个模态框里最多可以放 5 个。)
- label:显示在输入框上方的名称标签。
- style:可以选择
discord.TextStyle.short(默认,单行)或discord.TextStyle.long(多行)。 - placeholder:什么都没输入时显示的灰色提示文字。
- required / max_length:是否必填和最大字数。设置为
required=False时,留空也能提交。 - on_submit:用户点击"提交"按钮时执行的函数。输入的值用
self.입력칸이름.value的形式取出(中间换成输入框的变量名,例如 subject)。
💡 这里的 ephemeral=True 是用"只有自己能看到的消息"来回复的选项。像建议、举报这类不该让别人看到的回复,用它正合适!
📌 第 2 步 - 用斜杠命令弹出模态框
按钮和下拉菜单都是装进 View 里发送的,但模态框不需要 View! 而是直接用 interaction.response.send_modal() 弹出。
intents = discord.Intents.default()
bot = commands.Bot(command_prefix="!", intents=intents)
@bot.event
async def on_ready():
await bot.tree.sync()
print(f"✅ {bot.user} 登录成功!")
@bot.tree.command(name="건의하기", description="来给服务器提个建议吧!")
async def suggest(interaction: discord.Interaction):
await interaction.response.send_modal(SuggestModal())重点是:send_modal() 必须是第一个响应。如果已经用 interaction.response.send_message() 等方式响应过,就无法再弹出模态框了。所以通常的写法是:用户一点斜杠命令,就立刻打开模态框。
📌 第 3 步 - 添加错误处理(可选)
为了应对提交模态框时出现的问题,加上 on_error 会更安全。
async def on_error(self, interaction: discord.Interaction, error: Exception):
await interaction.response.send_message(
"⚠️ 处理时出错了,请稍后再试。", ephemeral=True
)
print(error)把这个函数放进上面的 SuggestModal 类里,写在 on_submit 下方并保持相同的缩进即可。
📌 完整代码(可直接复制)
# discord.py 2.x / Python 3.8+
import discord
from discord.ext import commands
class SuggestModal(discord.ui.Modal, title="建议箱 📮"):
subject = discord.ui.TextInput(
label="标题",
placeholder="请输入建议标题",
max_length=50,
)
content = discord.ui.TextInput(
label="内容",
style=discord.TextStyle.long,
placeholder="请自由填写详细内容!",
required=True,
max_length=500,
)
async def on_submit(self, interaction: discord.Interaction):
await interaction.response.send_message(
f"✅ 建议已提交!\n**标题:** {self.subject.value}\n**内容:** {self.content.value}",
ephemeral=True,
)
async def on_error(self, interaction: discord.Interaction, error: Exception):
await interaction.response.send_message(
"⚠️ 处理时出错了,请稍后再试。", ephemeral=True
)
print(error)
intents = discord.Intents.default()
bot = commands.Bot(command_prefix="!", intents=intents)
@bot.event
async def on_ready():
await bot.tree.sync()
print(f"✅ {bot.user} 登录成功!")
@bot.tree.command(name="건의하기", description="来给服务器提个建议吧!")
async def suggest(interaction: discord.Interaction):
await interaction.response.send_modal(SuggestModal())
bot.run("在这里填入机器人Token")📌 运行结果
输入 /건의하기(即"提建议")后,屏幕中央会弹出"建议箱"窗口,里面有标题和内容两个输入框。填写完点击提交,就会收到一条只有自己能看到的"建议已提交!"消息。

💡 附加内容:如果想把收到的内容发到管理员频道,只要在 on_submit 里找到指定频道,再用 Embed 发送过去,一个真正的"建议箱机器人"就完成了!
async def on_submit(self, interaction: discord.Interaction):
log_channel = interaction.guild.get_channel(관리자채널_ID)
embed = discord.Embed(title=f"📮 新建议:{self.subject.value}", description=self.content.value)
embed.set_footer(text=f"提交者:{interaction.user}")
await log_channel.send(embed=embed)
await interaction.response.send_message("✅ 建议已提交!", ephemeral=True)📌 常见错误
1. InteractionResponded: This interaction has already been responded to
对已经响应过的交互再次调用 send_modal() 时就会出现这个错误。模态框必须作为第一个响应弹出。在按钮回调等地方做出其他响应之后,就无法再打开模态框了。
2. 输入框有 6 个以上,弹窗不显示
一个模态框里最多只能放 5 个 TextInput。如果需要接收更多内容,请把内容拆开,设计成多个步骤。
3. AttributeError: 'str' object has no attribute 'value'
取出输入值时,不能只写 self.subject,必须像 self.subject.value 这样加上 .value,才能拿到实际的文字。漏掉 .value 的话,拿到的会是 TextInput 对象本身。
📌 总结
今天我们学习了如何用模态框(Modal)让用户直接输入文本!从按钮 → 下拉菜单 → 模态框一路走来,Discord 的交互 UI 基本都已经讲过一遍了 🙌 下一篇我们来讲讲如何在 Embed 中加入图片和字段,把它装饰得更漂亮。敬请期待!
📚 Discord 机器人开发系列 #4 用 Slash Command 发送 Embed #5 实现按钮(Button)交互 #6 实现下拉菜单(Select Menu) #7 用模态框(Modal)接收输入 ← 就是这篇!
连载 · 共 32 篇中的第 7 篇
Discord 机器人开发
- #1Discord 机器人开发 - Slash Command 完全攻略!
- #2为 Slash Command 添加选项(Arguments)!
- #3在 Slash Command 中添加子命令(Subcommand)!
- #4用 Slash Command 发送 Embed 嵌入消息!
- #5实现按钮(Button)交互!
- #6实现下拉菜单(Select Menu)!
- #7用模态框(Modal)接收用户输入(Python 示例)当前文章
- #8用嵌入消息(Embed)的图片和字段美化消息(Python 示例)
- #9接入 AI(Claude·ChatGPT API)!(Python 示例)
- #10支持多语言(i18n)!(Python 示例)
- #11用 Flask 制作网页仪表盘!(Python 示例)
- #12管理命令冷却时间(Cooldown)与权限(Permission)!(Python 示例)
- #13用身份组·频道自动化管理服务器!(Python 示例)
- #14保存数据!JSON vs SQLite(Python 示例)
- #15슬래시 명령어 그룹(Group)으로 명령어 정리하기! (파이썬 예제) (韩语)
- #16리마인더·알림 기능 만들기! 봇이 먼저 말 걸게 하기 (파이썬 예제) (韩语)
- #17RAG로 문서 기반 답변봇 만들기! 우리 서버 전용 FAQ 봇 (파이썬 예제) (韩语)
- #18투표(Poll) 기능 만들기! 다수결로 정하는 서버 규칙 (파이썬 예제) (韩语)
- #19Cog로 코드 쪼개기! 1000줄 봇도 안 더러워지는 구조 (파이썬 예제) (韩语)
- #20자동 환영 메시지·온보딩 만들기! 규칙 동의 버튼으로 자동 역할 부여 (파이썬 예제) (韩语)
- #21키워드 자동응답·금지어 필터 만들기! 경고 누적으로 자동 제재까지 (파이썬 예제) (韩语)
- #22슬래시 명령어 자동완성(Autocomplete) 만들기! 금지어를 골라서 추가·삭제 (파이썬 예제) (韩语)
- #23aiosqlite로 비동기 DB 제대로 설계하기! JSON 탈출 (파이썬 예제) (韩语)
- #24채널 난독화(Channel Obfuscation) 대응하기! 11/16부터 안 보이는 채널이 생겨요 (파이썬 예제) (韩语)
- #25봇이 죽지 않게! 에러 핸들링·로깅 체계 잡기 (파이썬 예제) (韩语)
- #26티켓(Ticket) 문의 시스템 만들기! 버튼 하나로 1:1 상담 채널 자동 생성 (파이썬 예제) (韩语)
- #27티켓 담당자 배정·우선순위 만들기! 스태프가 여러 명이어도 안 꼬이게 (파이썬 예제) (韩语)
- #28레벨·경험치(XP) 시스템 만들기! 채팅할수록 레벨업, 랭킹판까지 (파이썬 예제) (韩语)
- #29화폐·상점(Economy) 시스템 만들기! 코인 벌어서 아이템 사기 (파이썬 예제) (韩语)
- #30打造投票·问卷(Poll)机器人!原生投票 + 按钮实时统计(Python 示例)🗳️
- #32打造服务器日志·审核日志(Audit Log)频道!自动记录消息删除、编辑、成员进出和踢出(Python 示例)🕵️
- #33임시 음성방 확장, 파티방 만들기! 방장 위임·강퇴·초대 전용(비공개) 방 + 전용 채팅방 자동 생성 (파이썬 예제) 🎉 (韩语)
