Discord.py开发!view命令:如何将SQLite3租赁数据逐行渲染为独立Discord Embed
核心实现思路
- 你当前用
for x in rows逐行遍历数据库查询结果的大逻辑是完全正确的,完全可以沿用你之前处理用户实时输入、用字符串格式化填充Embed的逻辑。本质上数据库返回的每一行元组,和你之前暂存的用户输入值没有任何区别,只要取出对应位置的字段值替换Embed占位符即可。 - 你之前代码的核心问题集中在3点:
- 没有将元组中对应字段的值填充到Embed占位符里,写死的
'{}'只是普通字符串,没有实际执行格式化操作 - SQL查询的字段顺序和Embed所需字段不匹配,你遗漏了租赁价格字段,还把“租赁名称”的字段名错写成了“Bot Name”
- 默认SQLite返回的元组没有字段标识,靠数字索引取值很容易因查询顺序变动出现填充错位
- 没有将元组中对应字段的值填充到Embed占位符里,写死的
修正步骤与参考实现
第一步:调整SQLite配置降低出错概率
在你初始化数据库连接的位置加一行配置,让所有查询返回的行支持通过字段名取值,不需要靠数字下标数顺序:
# 初始化数据库连接后配置 conn = sqlite3.connect('rentals.db') conn.row_factory = sqlite3.Row # 将查询返回行转为类字典结构 cursor = conn.cursor()
配置完成后,后续查询的每一行都可以通过x['name']、x['renter']这类字段名直接取值,从根源避免索引错位问题。
第二步:修正!view命令的字段填充逻辑
将你之前循环内的占位符替换为实际字段取值,使用你熟悉的字符串格式化逻辑即可,参考代码如下:
# 文件顶部提前导入需要的依赖 import asyncio import discord if message.content.startswith('!view'): rows = cursor.execute("SELECT name, renter, duration, price, start, end FROM rental").fetchall() # 没有查询到记录时直接提示,避免发送空内容的Embed if not rows: await message.channel.send("目前还没有存储任何租赁记录") return for rental in rows: embed = discord.Embed(title="租赁详情", color=0x0000FF) embed.set_thumbnail(url="https://icon-library.com/images/database-png-icon/database-png-icon-22.jpg") # 直接通过字段名取值填充,和你处理用户输入的逻辑完全一致 embed.add_field(name='租赁名称', value=rental['name'], inline=False) embed.add_field(name='承租方名称', value=rental['renter'], inline=False) embed.add_field(name='租赁时长', value=f"{rental['duration']} 天", inline=False) embed.add_field(name='租赁价格', value=rental['price'], inline=False) embed.add_field(name='开始日期', value=rental['start'], inline=False) embed.add_field(name='结束日期', value=rental['end'], inline=False) embed.set_footer(icon_url='https://pbs.twimg.com/profile_images/1325672283881484289/oaGtVIOD_400x400.png', text='Created by @Expected') await message.channel.send(embed=embed) # 记录较多时加0.5秒延时,避免短时间发消息触发Discord速率限制 await asyncio.sleep(0.5)
注意事项
- 如果你不想调整SQLite的行工厂配置,也可以直接用原来的元组索引取值:按照你当前的SQL查询顺序
name, renter, duration, price, start, end,元组的0到5位依次对应上述字段,直接用rental[0]到rental[5]取值即可,但这种方式在后续修改查询字段顺序时很容易出现填充错位,不推荐长期使用。 - 你之前写的
value='{}'没有生效,本质是没有对字符串执行格式化操作,不管是用'{}'.format(取值)、f-string这类常见格式化方式,在数据库取值场景下和用户输入场景下是完全通用的,不存在适配差异。 - 如果后续租赁记录数量较多,逐行发独立Embed的体验可以进一步优化,但当前你要求单条记录对应单条独立Embed的需求,上述代码可以直接满足。
内容的提问来源于stack exchange,提问作者Aqyl
相关产品推荐
相关产品推荐

