如何在Django页面展示Telegram API获取的消息?含缓存优化咨询
在Django中展示Telegram提取的消息(含YouTube链接)
我拥有Telegram API用于获取消息,通过以下Telethon代码可提取需在网页展示的消息(含YouTube链接):
from telethon import TelegramClient, events, sync from telethon.tl.types import MessageMediaWebPage, WebPageEmpty client = TelegramClient(session_name, api_id, api_hash) client.start() for message in client.iter_messages(chat, reverse=True): if type(message.media) == type(None): continue if not type(message.media) == MessageMediaWebPage: continue if type(message.media.webpage) == WebPageEmpty: continue if hasattr(message.media.webpage, 'display_url'): print('+++ display_url ', message.media.webpage.display_url)
问题1:该从何处入手,如何直接在网页展示Telegram返回的数据?
按以下步骤落地:
- 封装数据获取逻辑:把Telethon的代码封装成独立函数,比如
get_telegram_youtube_links(chat_id),返回提取到的display_url列表,方便在Django中调用。同时把api_id、api_hash、session_name这些配置移到Django的settings.py中,避免硬编码。 - 编写Django视图:在视图中调用封装好的函数获取链接列表,将数据传入模板上下文。
- 编写模板渲染数据:创建Django模板,用循环遍历链接列表,将每个URL渲染成可点击的链接;若为YouTube链接,还可以直接嵌入iframe播放器提升体验。
示例代码片段:
# views.py from django.shortcuts import render from telethon import TelegramClient from telethon.tl.types import MessageMediaWebPage, WebPageEmpty from django.conf import settings from django.core.cache import cache def get_telegram_links(): client = TelegramClient(settings.TELEGRAM_SESSION_NAME, settings.TELEGRAM_API_ID, settings.TELEGRAM_API_HASH) client.start() links = [] try: for message in client.iter_messages(settings.TELEGRAM_CHAT_ID, reverse=True): if not message.media or not isinstance(message.media, MessageMediaWebPage): continue if isinstance(message.media.webpage, WebPageEmpty): continue if hasattr(message.media.webpage, 'display_url'): links.append(message.media.webpage.display_url) finally: client.disconnect() return links def telegram_links_view(request): links = get_telegram_links() return render(request, 'telegram_links.html', {'links': links})
模板示例(telegram_links.html):
{% for link in links %} {% if 'youtube.com' in link or 'youtu.be' in link %} <iframe width="560" height="315" src="{{ link|replace:'watch?v=,embed/' }}" frameborder="0" allowfullscreen></iframe> {% else %} <a href="{{ link }}" target="_blank">{{ link }}</a> {% endif %} <br> {% endfor %}
问题2:是否可在Django视图中调用上述循环?
可以直接在视图中调用,但需要注意几个细节:
- 避免请求阻塞:如果聊天消息量很大,
iter_messages会耗时较久,同步视图会导致用户等待时间过长。建议优先使用Django异步视图(Django 3.1+支持),或者将数据拉取操作放到后台任务(如Celery)中,视图直接读取预拉取的数据。 - 客户端复用与资源释放:不要每次请求都重新创建TelegramClient,可复用会话文件减少登录开销;同时要确保在操作完成后调用
client.disconnect()释放资源,避免连接泄漏。 - 异常处理:添加try-except块捕获API调用失败、网络异常等情况,返回友好的错误提示,避免页面崩溃。
问题3:每次页面加载查询Telegram耗时久,如何缓存API数据优化后续读取?
可以通过以下几种方式优化:
- 使用Django自带缓存框架:将获取到的链接列表缓存到内存、Redis或数据库中,设置合理的过期时间(如15-30分钟)。每次请求先读取缓存,缓存失效时再调用Telegram API更新缓存。
示例代码:from django.core.cache import cache def get_telegram_links(): cache_key = 'telegram_youtube_links' links = cache.get(cache_key) if not links: # 原有Telethon数据拉取逻辑 client = TelegramClient(settings.TELEGRAM_SESSION_NAME, settings.TELEGRAM_API_ID, settings.TELEGRAM_API_HASH) client.start() links = [] try: for message in client.iter_messages(settings.TELEGRAM_CHAT_ID, reverse=True, limit=50): if not message.media or not isinstance(message.media, MessageMediaWebPage): continue if isinstance(message.media.webpage, WebPageEmpty): continue if hasattr(message.media.webpage, 'display_url'): links.append(message.media.webpage.display_url) finally: client.disconnect() cache.set(cache_key, links, 60*15) # 缓存15分钟 return links - 后台定时拉取数据:用Celery+Beat定时任务定期拉取Telegram数据,将结果存入数据库,视图直接从数据库读取数据,彻底避免页面加载时调用API的延迟。
- 限制拉取数量:在
iter_messages中添加limit参数,只拉取最新的N条消息(如iter_messages(chat, reverse=True, limit=50)),减少API请求的数据量和耗时。
内容的提问来源于stack exchange,提问作者nish
相关产品推荐
相关产品推荐

