Изменение данных сущности транзакционно или нет (в зависимости от необходимости)
Каков наилучший способ сохранить код модульным и развязанным, но не вводить транзакцию дважды?
У организаций часто есть методы класса для загрузки, изменения и хранения данных. Часто это должно быть транзакционным, чтобы оно соответствовало объектам child / sibling / cousin. Вот шаблон:
class MyEntity(db.Model): # ... some properties @classmethod def update_count(cls, my_key): def txn(): me = db.get(my_key) me.count += 23 me.put() OtherEntity.update_descendants(ancestor=me) return db.run_in_transaction(txn)
Обычно вы должны извлекать сущности, изменять их и хранить их в блоке. Эта техника более эффективна; но иногда производительность менее важна, чем модульность и ремонтопригодность. Два обновления должны быть развязаны. (Возможно, update_descendants
вызывается часто изолированно и отвечает за хранение данных.)
Но следующий код является ошибкой:
class OtherEntity(db.Model): # ... some properties @classmethod def update_descendants(cls, ancestor): def txn(): # XXX Bug! descendants = cls.all().ancestor(ancestor).fetch(10) for descendant in descendants: descendant.update_yourself(ancestor.count) db.put(descendants) return db.run_in_transaction(txn)
Это вызывает исключение:
>>> MyEntity.update_count(my_key=some_key_i_have) Traceback (most recent call last): ... BadRequestError: Nested transactions are not supported.
Итак, как я могу получить лучшее из обоих миров: модульность и правильность?
- Как сравнить переменные и найти разницу в python
- Как читать файл конфигурации с помощью python
- PyCharm заменяет символы в docstrings
- Pythonic способ выбора элементов списка с разной вероятностью
- Проверка учетных записей пользователей с помощью электронной почты (Google App Engine)
Я использую шаблон, чтобы иметь параметр, указывающий, требуется ли транзакционное поведение.
class OtherEntity(db.Model): # ... some properties @classmethod def update_descendants(cls, ancestor, with_transaction=True): if with_transaction: return db.run_in_transaction(cls.update_descendants, ancestor, with_transaction=False) # Now I can assume I am in a transaction one way or another... descendants = cls.all().ancestor(ancestor).fetch(10) for descendant in descendants: descendant.update_yourself(ancestor.count) return db.put(descendants)
Тот же принцип можно было бы расширить, чтобы указать, следует ли брать на себя ответственность за put
или оставить его вызывающему.
Я бы предложил сделать функции транзакций методами класса верхнего уровня. Затем вы можете вызвать их напрямую или с помощью db.run_in_transaction
, если это необходимо.
- длительность python файлового объекта в списке аргументов
- Python: Regex расщепляется на пробел (но сохраняйте элементы unsplitted в ) и добавляйте «" в массив как символ Newline
- OrderedDict для более старых версий python
- Несколько имен полей в поиске приложений
- Новое для Python – попытка кодирования сантиметра в дюймах и наоборот
- Найти наибольшие размеры изображения из списка изображений
- проблемы с окружающей средой носа-гэ
- Что я должен использовать вместо назначения в выражении в Python?
- Как передать функцию как переменную с фиксированным аргументом
- Ошибка при запуске Google App Engine: невозможно открыть файл базы данных
- Mac для Windows Python