Using transactions on Django AppEngine

蹲街弑〆低调 提交于 2019-12-05 22:34:32

As the error message suggests, only certain types of query are permissible inside a transaction on App Engine - specifically, ones that apply a .ancestor() filter. Queries such as the one you're attempting to execute can't be executed transactionally.

One option would be to execute the query outside the transaction, and pass the results in. It looks like you're trying to retrieve a specific shard of a sharded counter by name, though, and that ought to be possible without using a query at all, since it ought to be identified by its key name. Since I'm not familiar with Django's model API, though, I can't suggest how you'd do this in Django.

Nailer hit it on the head in his answer (sorry for the pun): DjangoAE does not support entity groups. However, there is unofficial support in this enterprising developer's branch of djangoappengine.

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

The patch is not yet complete, but I plan on trying it out in the next few weeks and will update here.

A Django port of the AppEngine WebApp Sharded Counter example, including transactions on regular Django objects, lives in:

https://bitbucket.org/twanschik/sharded-counters-nonrel. Check out sharded_counters/models.py , which includes a single read/increment/write operation as discussed.

Specifically the @commit_locked decorator can be used to read/write/increment a Django model atomically.

Note however you are limited in the queries you can make inside a transaction: Django nonrel, as of Jan 2011, does not support entity groups, which is the cause of the error above.

A more elegant way is available:

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

Another example is availabe here: 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)
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!