Django LRU_Cache с помощью вызовов API
Я пытаюсь использовать API Reddit через PRAW (https://praw.readthedocs.io/en/stable/) в Django и думаю попробовать использовать декоратор functools lru_cache
для реализации некоторого вида кэширования, чтобы я мог кэшировать результаты похожих вызовов API для уменьшения общего количества вызовов. Я никогда не делал ничего подобного, поэтому в основном слежу за примерами реализации декоратора @lru_cache
.
У меня есть 3 файла, которые в основном связаны с вызовами API / отображением здесь. У меня есть:
account.html
{% extends 'myapp/base.html' %}
<h1> {{ name }} </h1>
<h3> {{ comment_karma }} </h3>
<h5> Top Posts </h5>
<table>
<tr>
<th> Post </th>
<th> Subreddit </th>
</tr>
{% for s in top_submissions %}
<tr>
<td> {{ s.title }} </td>
<td> {{ s.subreddit }} </td>
</tr>
{% endfor %}
</table>
views.py
from . import reddit
reddit = reddit.Reddit()
def account_page():
context = reddit.details(request.user.reddit_username)
return render(request, 'stats/dashboard.html', context)
reddit.py
from functools import lru_cache
class Reddit:
def __init__(self):
self.praw = praw.Reddit(
client_id = CLIENT_ID,
client_secret = CLIENT_SECRET,
user_agent = USER_AGENT
)
@lru_cache(maxsize = 256)
def details(self, redditor):
redditor = self.praw.redditor(redditor)
overview = {
'name': redditor.name,
'comment_karma': redditor.comment_karma,
'top_submissions': redditor.submissions.top(limit=10),
}
return overview
Вот в чем проблема: когда у меня нет lru_cache, то все работает нормально и все данные приходят как всегда. Однако, когда я устанавливаю опцию lru_cache, то приходят только имя и comment_karma, а submissions (итерируемый список) просто не отображается на моей странице (поэтому я предполагаю, что он не имеет никаких значений).
Я неправильно использую lru_cache? По сути, моя цель состоит в том, что если redditor
передается в функцию overview
, я не хочу продолжать делать одни и те же вызовы API снова и снова, а вместо этого хочу поместить его в кэш и извлечь те же данные, если они есть в кэше.
PRAW возвращает объекты генератора, которые лениво оцениваются. Вы хотите оценивать их внутри вашей кэшированной функции. В противном случае после исчерпания генератора вы не сможете получить результаты снова.
Таким образом, рабочая версия должна выглядеть следующим образом:
@lru_cache(maxsize = 256)
def details(self, redditor):
redditor = self.praw.redditor(redditor)
overview = {
'name': redditor.name,
'comment_karma': redditor.comment_karma,
'top_submissions': list(redditor.submissions.top(limit=10)),
}
return overview
list(redditor.submissions.top(limit=10))
будет потреблять генератор, и кэшированный результат будет содержать список, а не объект генератора, который может быть потреблен только один раз.