Как контекстно кешировать метод класса результата в Python - PullRequest
0 голосов
/ 29 октября 2019

У меня есть модель django, которая реализует метод, выполняющий запросы к базе данных. Во время процесса импорта этот метод будет вызываться в другой части кода. Я хочу избежать нескольких запросов к базе данных, потому что я знаю, что результат будет одинаковым во время процесса импорта. Этот метод будет вызываться во многих частях кода, и мне будет трудно внедрить зависимости.

Я ищу способ сделать это с помощью диспетчера контекста, но, возможно, это не лучшийопция:

class OrganizationSettings(models.Model):
  year = models.IntegerField()

  @classmethod
  def for_year(cls, year):
      return cls.objects.get(year=year)


class CacheOrganizationSettings():
  def __init__():
      # ???
      pass

  def __enter__(self):
      # ???
      pass

  def __exit__(self, type, value, traceback):
      # ???
      pass


def process():
  # Somewhere in the (deep)code this is called many times :
  settings = OrganizationSettings.for_year(2018)
  # ...
  OrganizationSettings.for_year(2019)
  # ...
  OrganizationSettings.for_year(2018)


# No cache used (query at each call)
process()

# With cache (query, one by year)
with CacheOrganizationSettings():
  process()

Я попробовал это, что работает, как ожидалось, но, вероятно, я что-то упустил:


class CacheOrganizationSettings():
    def __init__(self):
        pass

    def __enter__(self):
        OrganizationSettings.__original_for_year__ = OrganizationSettings.for_year
        OrganizationSettings.for_year = functools.lru_cache()(OrganizationSettings.for_year)

    def __exit__(self, _type, value, traceback):
        OrganizationSettings.for_year = OrganizationSettings.__original_for_year__

...