如何通过discord.py从Django应用发送非事件触发的Discord消息
使用discord.py在Django应用中通过机器人发送Discord消息
完全可以用discord.py实现你的需求,虽然discord.py本身是事件驱动的异步框架,但可以通过异步同步转换的方式,让Django的同步视图触发机器人发送消息,还能顺便添加反应。
核心实现思路
discord.py的Bot客户端是异步运行的,而Django默认是同步框架,所以需要解决异步函数的调用问题,同时确保Bot实例持续在线。
具体步骤
准备Discord机器人
- 在Discord开发者平台创建机器人,获取Token
- 邀请机器人到目标服务器,确保它拥有「发送消息」「添加反应」的频道权限
- 记录目标频道的ID(开启开发者模式后右键频道可复制)
安装依赖
在Django项目环境中安装discord.py和异步转换工具:pip install discord.py asgiref编写Discord机器人异步函数
创建一个单独的文件(比如discord_bot.py),定义发送消息并添加反应的逻辑:import discord from discord.ext import commands # 配置机器人Intents,按需开启需要的权限 intents = discord.Intents.default() intents.message_content = True bot = commands.Bot(command_prefix='!', intents=intents) @bot.event async def on_ready(): print(f"机器人已登录:{bot.user}") async def send_discord_message(channel_id, content): # 等待机器人完成登录初始化 await bot.wait_until_ready() # 获取目标频道 channel = bot.get_channel(channel_id) if not channel: return None # 发送消息 message = await channel.send(content) # 给消息添加反应 await message.add_reaction('👍') return message.id在Django视图中调用异步函数
利用asgiref.sync.async_to_sync将异步函数转换为同步调用,在视图中处理用户请求:from django.http import HttpResponse from asgiref.sync import async_to_sync from django.views.decorators.http import require_POST from .discord_bot import send_discord_message, bot import asyncio import threading # 启动机器人事件循环(放在AppConfig中确保项目启动时运行) def start_bot(): loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) loop.run_until_complete(bot.start('你的机器人Token')) # 在Django应用的apps.py中配置启动: # from django.apps import AppConfig # class MyAppConfig(AppConfig): # default_auto_field = 'django.db.models.BigAutoField' # name = 'myapp' # def ready(self): # threading.Thread(target=start_bot, daemon=True).start() @require_POST def send_message(request): content = request.POST.get('message_content', '') if not content: return HttpResponse("消息内容不能为空") channel_id = 123456789012345678 # 替换为你的目标频道ID message_id = async_to_sync(send_discord_message)(channel_id, content) if message_id: return HttpResponse(f"消息发送成功,消息ID:{message_id}") else: return HttpResponse("发送失败:未找到指定频道或机器人无权限")
注意事项
- 机器人实例需要持续运行,用后台线程启动事件循环是常用方式,也可以考虑用独立进程运行机器人,通过Redis等IPC方式和Django通信(这种方式更稳定,避免同步异步冲突)
- 务必开启正确的Intents,比如
message_content权限,否则机器人无法正常处理消息操作 - 确保机器人在目标频道拥有足够的权限,否则会抛出权限错误
内容的提问来源于stack exchange,提问作者knowledge_seeker
相关产品推荐
相关产品推荐

