django 如何在Telegram bot中使数据库调用异步?

disbfnqx  于 12个月前  发布在  Go
关注(0)|答案(1)|浏览(162)

我有一个Django应用程序,它运行Telegram聊天机器人脚本作为命令。
我用python manage.py runserver启动Django应用程序,用python manage.py bot启动Telegram客户端。
我想在用户在telegram聊天中输入“/animals”时调用的ORM方法中列出Animal表中的条目。如果我使用硬编码列表或字典作为数据源,我的代码就可以工作。但是,我无法让ORM调用在ORM模式下工作。
文件结构:

|Accounts---------------------
|------| models.py------------
|Main-------------------------
|------| Management-----------
|---------------| Commands----
|-----------------------bot.py

字符串
动物模型:

class Animal(models.Model):
    id = models.AutoField(primary_key=True)
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    name = models.CharField(max_length=255)


我从文件中删除了很多,只留下相关的部分。
bot.py

# removed unrelated imports
from asgiref.sync import sync_to_async
from accounts.models import Animal

class Command(BaseCommand):
    help = "Starts the telegram bot."
    # assume that the token is correct
    TOKEN = "abc123"

    def handle(self, *args, **options):

        async def get_animals():
            await Animal.objects.all()

        async def animals_command(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:

            async_db_results = get_animals()

            message = ""
            counter = 0
            for animal in async_db_results:
                message += animal.name + "\n"
                counter += 1

            await update.message.reply_text(message)

        application = Application.builder().token(TOKEN).build()
        application.add_handler(CommandHandler("animals", animals_command))
        application.run_polling(allowed_updates=Update.ALL_TYPES)


此代码的错误消息:
TypeError:'coroutine'对象不可迭代
最初我用Animal.objects.all()代替了async_db_results。ORM调用不是pixec,所以我得到了这个错误消息:

django.core.exceptions.SynchronousOnlyOperation: You cannot call this from an async context - use a thread or sync_to_async.


这是一个原型应用程序,我知道我不应该使用runserver。我也应该使用webhook而不是长轮询,但我不认为这些问题与我的问题有关。
接下来我要尝试的是使用Paddio,但我已经花了很多时间,我想我会问这个问题。
我看了这些资源(和许多其他资源):
docs.djangoproject.com:asgiref.sync.sync_to_blog c
stackoverflow: Django: SynchronousOnlyOperation: You cannot call this from an async context - use a thread or sync_to_async
stackoverflow: Sync to Async Django ORM queryset foreign key property

zphenhs4

zphenhs41#

我想明白了。正确使用sync_to_asyncawait就可以了。

@sync_to_async
def get_animals():
    return list(Animal.objects.all())

async def animals_command(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
    """Send a message when the command /animal is issued."""
    async_db_results = await get_animals()

    message = "Animal list:"
    for h in async_db_results:
        message += "{}\n".format(h.name)

    await update.message.reply_text(message)

字符串

相关问题