Discord.py中给Modal添加discord.ui.Select报错及替代方案咨询
解决Discord Modal中无法使用Select组件的问题
错误原因
报错信息Value of field "type" must be one of (4,)明确说明:Discord的Modal组件仅支持类型为4的组件(即TextInput文本输入框),API层面不允许在Modal中添加Select下拉选择器,这是核心限制,所以添加Select后会触发400 Bad Request错误。
替代方案(适配View场景)
因为你使用的是View而非斜杠命令,无法直接用Literal参数,以下是三个可行的替代思路:
方案1:用单选按钮组替代Select
先展示包含分类选项的按钮View,用户选择后再弹出仅含TextInput的Modal收集工单原因。
示例代码:
class TicketCategoryView(discord.ui.View): def __init__(self): super().__init__(timeout=90) self.selected_category = None @discord.ui.button(label="Become an admin", emoji="👮", style=discord.ButtonStyle.primary) async def admin_btn(self, interaction: discord.Interaction, button: discord.ui.Button): self.selected_category = "Become an admin" self.stop() await interaction.response.send_modal(TicketReasonModal(self.selected_category)) @discord.ui.button(label="A script problem", emoji="📜", style=discord.ButtonStyle.primary) async def script_btn(self, interaction: discord.Interaction, button: discord.ui.Button): self.selected_category = "A script problem" self.stop() await interaction.response.send_modal(TicketReasonModal(self.selected_category)) @discord.ui.button(label="Other ...", emoji="🤔", style=discord.ButtonStyle.primary) async def other_btn(self, interaction: discord.Interaction, button: discord.ui.Button): self.selected_category = "Other ..." self.stop() await interaction.response.send_modal(TicketReasonModal(self.selected_category)) class TicketReasonModal(discord.ui.Modal): def __init__(self, category): super().__init__(title="Ticket", timeout=90) self.category = category self.add_item(discord.ui.TextInput(label="Raison", placeholder="Raison du ticket", custom_id="reason_input", max_length=50, min_length=10)) async def on_submit(self, interaction: discord.Interaction): reason = self.children[0].value embed = discord.Embed(title=f"Ticket created!", color=discord.Color.blurple()) embed.add_field(name="**Salon**", value=f"{ticket_channel_mention}", inline=True) embed.add_field(name="**Category**", value=f"{self.category}", inline=True) embed.add_field(name="**Raison**", value=f"{reason}", inline=True) embed.set_thumbnail(url=icon_url) await interaction.response.send_message(embed=embed, ephemeral=True)
方案2:用TextInput配合关键词验证
在Modal中添加两个TextInput,第一个要求用户输入指定分类关键词(如admin/script/other),提交时验证输入合法性,不符合则提示重新输入。
示例代码:
class TicketInputReason(discord.ui.Modal): def __init__(self): super().__init__(title="Ticket", timeout=90) self.add_item(discord.ui.TextInput(label="Catégorie du ticket", placeholder="输入 admin/script/other 选择分类", custom_id="category_input", max_length=10, min_length=4)) self.add_item(discord.ui.TextInput(label="Raison", placeholder="Raison du ticket", custom_id="reason_input", max_length=50, min_length=10)) async def on_submit(self, interaction: discord.Interaction): category_input = self.children[0].value.lower() category_map = { "admin": "Become an admin 👮", "script": "A script problem 📜", "other": "Other ... 🤔" } if category_input not in category_map: await interaction.response.send_message("请输入正确的分类关键词:admin/script/other", ephemeral=True) return category = category_map[category_input] reason = self.children[1].value embed = discord.Embed(title=f"Ticket created!", color=discord.Color.blurple()) embed.add_field(name="**Salon**", value=f"{ticket_channel_mention}", inline=True) embed.add_field(name="**Category**", value=f"{category}", inline=True) embed.add_field(name="**Raison**", value=f"{reason}", inline=True) embed.set_thumbnail(url=icon_url) await interaction.response.send_message(embed=embed, ephemeral=True)
方案3:先显示Select菜单View,再弹出Modal
保留原有的Select组件逻辑,但将其放在独立的View中,用户选择分类后再触发原因收集的Modal。
示例代码:
class TicketCategorySelect(discord.ui.View): def __init__(self): super().__init__(timeout=90) options = [ discord.SelectOption(label="Become an admin", emoji="👮"), discord.SelectOption(label="A script problem", value="script", emoji="📜"), discord.SelectOption(label="Other ...", value="Other", emoji="🤔") ] self.add_item(discord.ui.Select( placeholder="Catégorie du ticket", options=options, custom_id="category_select", min_values=1, max_values=1)) async def on_select(self, interaction: discord.Interaction, select: discord.ui.Select): selected_category = select.values[0] self.stop() await interaction.response.send_modal(TicketReasonModal(selected_category)) class TicketReasonModal(discord.ui.Modal): def __init__(self, category): super().__init__(title="Ticket", timeout=90) self.category = category self.add_item(discord.ui.TextInput(label="Raison", placeholder="Raison du ticket", custom_id="reason_input", max_length=50, min_length=10)) async def on_submit(self, interaction: discord.Interaction): reason = self.children[0].value embed = discord.Embed(title=f"Ticket created!", color=discord.Color.blurple()) embed.add_field(name="**Salon**", value=f"{ticket_channel_mention}", inline=True) embed.add_field(name="**Category**", value=f"{self.category}", inline=True) embed.add_field(name="**Raison**", value=f"{reason}", inline=True) embed.set_thumbnail(url=icon_url) await interaction.response.send_message(embed=embed, ephemeral=True)
内容的提问来源于stack exchange,提问作者Le Rat Gondin
相关产品推荐
相关产品推荐

