SQLAlchemy Уникальный объектный шаблон - PullRequest
2 голосов
/ 19 апреля 2020

Раньше я работал над проектом, который включал версию шаблона Уникальный объект . Этот конкретный код был написан не мной, и в поисках информации я нашел оригинальный рецепт. Я пытаюсь понять это, но некоторые детали приходят мне в голову.

Реализация, которая была сделана в проекте, очень похожа на ту, что представлена ​​в вики, но вместо _unique, get_unique реализован как метод класса общей базовой модели. Он принимает произвольные параметры и делает почти то же, что _unique делает в вики, но определившись с параметрами hashfunc, queryfunc и constructor:

class Model(Base):
    @classmethod
    def get_unique(cls, session, **kwargs):
        """Get or create an instance based on unique values.
        """
        cache = getattr(session, '_unique_cache', None)
        if cache is None:
            session._unique_cache = cache = {}

        key = (cls, tuple(kwargs.items()))
        o = cache.get(key)

        if o is not None and was_deleted(o):
            o = None

        if o is None:
            with session.no_autoflush:
                o = session.query(cls).filter_by(**kwargs).first()

            if o is None:
                o = cls(**kwargs)
                session.add(o)

            cache[key] = o

        return o

Мне известны некоторые предостережения эта реализация, будучи одним из наиболее важных фактов, что порядок kwargs имеет значение для построения key. Мои вопросы:

  1. Есть ли основания заключать запрос в контекст no_autoflush? Что будет не так, если облако программистов решит, вызывать get_unique с autoflush или без него? Рецепт вики также выполняет запрос с no_autoflush, и мне интересно, ускользает ли мое понимание от понимания.

  2. Почему объекты кэшируются? Я не вижу смысла кэшировать объекты, когда сессия уже выполняет аналогичную задачу и знает, когда нужно повторно извлечь объекты из базы данных.

  3. Поэтому неправильно со следующей реализацией, которая не использует кеш и позволяет программисту решить, требуется ли контекст no_autoflush?

class Model(Base):
    @classmethod
    def get_unique(cls, session, **kwargs):
        """Get or create an instance based on unique values.
        """
        o = session.query(cls).filter_by(**kwargs).first()
        if o is None:
            o = cls(**kwargs)
            session.add(o)
        return o
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...