discord.py中Button对象无user属性的AttributeError问题求助
问题分析与解决方案
错误原因
你遇到的AttributeError: 'Button' object has no attribute 'user'是因为按钮回调函数的参数顺序错误。在discord.py v2.x中,@discord.ui.button装饰的回调函数,正确的参数顺序是:self → interaction: discord.Interaction → button: discord.ui.Button(可选)。
你的代码中将button放在了interaction前面,导致discord.py调用函数时,把Interaction对象传给了button参数,把Button对象传给了interaction参数。后续代码中你尝试访问interaction.user,但此时的interaction实际是Button对象,自然没有user属性。
修复后的核心代码
修正参数顺序,并补充交互回应、私信权限检查、超时处理等必要优化:
class DepositView(discord.ui.View): def __init__(self): super().__init__(timeout=None) # 设置View永久有效,除非手动停止 @discord.ui.button(label='Пополнить!', custom_id='deposit_button', style=discord.ButtonStyle.primary) async def deposit_button_callback(self, interaction: discord.Interaction, button: discord.ui.Button): # 先回应交互,避免Discord显示"交互失败"提示 await interaction.response.send_message('已向你发送私信,请查看', ephemeral=True) # 检查用户是否允许接收私信 try: await interaction.user.send('Какую сумму вы хотите пополнить?') except discord.Forbidden: await interaction.followup.send('无法向你发送私信,请开启私信权限后重试', ephemeral=True) return # 等待用户回复,设置5分钟超时 try: response = await bot.wait_for( 'message', check=lambda m: m.author == interaction.user and isinstance(m.channel, discord.DMChannel), timeout=300 ) except asyncio.TimeoutError: await interaction.user.send('Время ожидания истекло,请重新发起存款请求') return try: amount = int(response.content) if amount <= 0: await interaction.user.send('Пожалуйста, введите положительное число') return total_amount = calculate_total_amount(amount) # 格式化金额为两位小数,符合货币显示规范 await interaction.user.send(f'Итоговая сумма к оплате: {total_amount:.2f}\nРеквизиты:\n...') request_id = generate_request_id() payment_channel = bot.get_channel(payment_channel_id) if payment_channel: await payment_channel.send( f'Запрос на пополнение!\n- user_id: {interaction.user.id}\n' f'- user_balance_wait: {amount}\n- DATE: {current_date()}' ) else: await interaction.user.send('Ошибка: не удалось найти канал для отправки запроса администрации') return save_payment_request(request_id, interaction.user.id, amount) await interaction.user.send( f'Платеж на рассмотрение. Номер запроса: {request_id}\n' f'Ожидайте подтверждения от администрации.' ) except ValueError: await interaction.user.send('Пожалуйста, введите корректное число.')
其他优化建议
- 数据库操作优化:使用上下文管理器确保数据库连接自动关闭,避免资源泄漏:
def save_payment_request(request_id, user_id, amount): try: with sqlite3.connect('ezshop_requests.db') as conn_requests: cursor_requests = conn_requests.cursor() cursor_requests.execute( 'INSERT INTO requests (requests_id, requests_user_id, requests_user_balance_wait) ' 'VALUES (?, ?, ?)', (request_id, user_id, amount) ) conn_requests.commit() except sqlite3.Error as e: print(f'Ошибка при сохранении запроса: {e}')
- 金额计算优化:保留两位小数,避免出现多位小数的不规范显示:
def calculate_total_amount(amount): return round(amount * 1.01, 2)
- 请求ID唯一性优化:替换随机数为UUID,避免生成重复ID:
import uuid def generate_request_id(): return str(uuid.uuid4().int)[:9] # 取UUID前9位数字,保证唯一性
内容的提问来源于stack exchange,提问作者Nico-Nico
相关产品推荐
相关产品推荐

