Использование транзакций в Django AppEngine

В документации 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), вы должны использовать функции, специфичные для платформы».


person mikemaccana    schedule 05.04.2011    source источник


Ответы (4)


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

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

person Nick Johnson    schedule 06.04.2011
comment
@nailer Запросы с фильтрами предков подходят, потому что они работают только с одной группой сущностей. - person Nick Johnson; 07.04.2011
comment
@nailer Нет, запрос предка возвращает только те объекты, у которых есть родительский объект, который является указанным вами предком. Это не зависит от типов сущностей. - person Nick Johnson; 13.04.2011
comment
@nailer Вам следует прочитать документацию хранилища данных об объектах, группах объектов и транзакциях: code.google.com/appengine/docs/python/datastore/entities.html - person Nick Johnson; 14.04.2011
comment
@nailer Я не эксперт по Django (и даже не пользователь Django) - вам придется спросить людей, не связанных с Django, как они раскрыли возможность выборки по ключу в App Engine. Вам определенно не нужно использовать здесь запрос. Что «прискорбного» в документации App Engine? - person Nick Johnson; 15.04.2011
comment
@nailer Мне очень жаль, что ты недоволен моим ответом. Ссылка, которую я дал на документы, описывает, что такое группа сущностей, и это именно то, о чем вы спрашивали. Как я уже сказал, я не знаком с django-nonrel. Если вы хотите узнать, как выполнять выборку по ключу в Django-nonrel, вам следует поискать django-nonrel docs, задать их в списке рассылки или опубликовать еще один вопрос здесь, в SO, задав этот конкретный вопрос. - person Nick Johnson; 18.04.2011
comment
@Nick: извините, если я раньше казался разочарованным, но я обнаружил, что существует неприятная ситуация, когда пользователи Django AppEngine оказываются раздавленными между Google и Django non-rel. Я ценю, что вы пытались помочь, но мне показалось, что мы просто болтали на необработанном AE по конкретному вопросу djangoappengine. - person mikemaccana; 20.04.2011
comment
@nailer Я не думаю, что в этом есть что-то «раздавленное» - ребята из Django Nonrel четко знают, как это работает, с тех пор, как они это написали. Если их нет здесь, чтобы ответить, вам придется искать их в другом месте. К сожалению, мы (отношения с разработчиками) не можем быть экспертами по всем фреймворкам, которые люди используют с App Engine. - person Nick Johnson; 21.04.2011
comment
@Nick: 'squashed' - это мои личные чувства как разработчика AE, использующего Django, хотя я понимаю, что ваши собственные чувства могут отличаться, вы упомянули, что сами не используете Django в appengine, поэтому я не совсем уверен, насколько они актуальны . Хотя официальная поддержка самого популярного веб-фреймворка на AppEngine, совершенно очевидно, была бы хороша для Google с точки зрения принятия AppEngine - в отличие от документации AE, предполагающей, что вы используете специфичную для Google структуру, такую ​​как WebApp, - я не думаю, что это место для этого обсуждения. - person mikemaccana; 21.04.2011

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

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

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

person speedplane    schedule 15.02.2012

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

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

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

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

person mikemaccana    schedule 19.04.2011

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

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)
person dipicore    schedule 13.02.2015