Использование транзакций в Django AppEngine - PullRequest
3 голосов
/ 05 апреля 2011

В документации AppEngine есть несколько примеров транзакций, использующих нативную технику AppEngine для выполнения транзакций запросов к нативным объектам.

По документам на http://www.allbuttonspressed.com/projects/django-nonrel [1], я бы хотелиспользовать транзакции AppEngine для запроса объектов Django.Это возможно?

def txn():
    index = random.randint(0, NUM_SHARDS - 1)
    shard_name = "shard" + str(index)
    counter = SimpleCounterShard.objects.filter(name=shard_name)
    # Make counter if it doesn't exist 
    if not len(counter):
        counter = SimpleCounterShard(name=shard_name)
    counter.count += 1
    counter.put()
db.run_in_transaction(txn)

В настоящее время происходит сбой: «Внутри транзакции разрешены только запросы предков».Я понимаю, что это просит меня сделать что-то с классом предка, но я не уверен, что или почему.

Любые советы?

[1] «Вы не можете использовать API транзакций Django. Если ваша конкретная БД поддерживает специальный тип транзакции (например, run_in_transaction () в App Engine), у васиспользовать платформо-зависимые функции. "

Ответы [ 4 ]

1 голос
/ 15 февраля 2012

Нейлер ударил его по голове в ответ (извините за каламбур): DjangoAE не поддерживает группы сущностей. Тем не менее, существует неофициальная поддержка в этой предприимчивой ветке разработчика djangoappengine.

https://github.com/django-nonrel/djangoappengine/pull/10

Патч еще не завершен, но я планирую опробовать его в ближайшие несколько недель и обновлю здесь.

1 голос
/ 06 апреля 2011

Как следует из сообщения об ошибке, в транзакции в App Engine допустимы только определенные типы запросов, в частности те, которые применяют фильтр .ancestor(). Такие запросы, как тот, который вы пытаетесь выполнить, не могут быть выполнены транзакционно.

Один из вариантов - выполнить запрос вне транзакции и передать результаты. Похоже, вы пытаетесь получить определенный фрагмент осколка счетчика по имени, и это должно быть возможно без использования запрос вообще, так как он должен быть идентифицирован по имени ключа. Так как я не знаком с API модели Django, я не могу предложить, как бы вы сделали это в Django.

0 голосов
/ 13 февраля 2015

Доступен более элегантный способ:

from django.db.models import F
Accumulator.objects.filter(pk=1).update(counter=F('counter') + 5)

https://www.allbuttonspressed.com/blog/django/f-objects-and-queryset-update-support-in-djangoappengine

Другой пример доступен здесь: https://www.allbuttonspressed.com/blog/django/2010/01/Sharding-with-Django-on-App-Engine#django-s-advantage

YouTubeVideo.objects.filter(pk=keyname).update(
    views_count=F('views_count')+1)
0 голосов
/ 19 апреля 2011

Порт Django из примера App Shadow WebApp Sharded Counter, включая транзакции с обычными объектами Django, находится в:

https://bitbucket.org/twanschik/sharded-counters-nonrel. Ознакомьтесь с sharded_counters / models.py, который включает в себя одну операцию чтения / увеличения / записи, как описано.

В частности, декоратор @ commit_locked может использоваться для атомарного чтения / записи / увеличения модели Django.

Обратите внимание, однако, что вы ограничены в запросах, которые вы можете сделать внутри транзакции: Django nonrel по состоянию на январь 2011 года не поддерживает группы сущностей , что является причиной вышеуказанной ошибки.

...