【问题标题】:Using transactions on Django AppEngine在 Django AppEngine 上使用事务
【发布时间】:2011-04-05 13:32:59
【问题描述】:

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] “您不能使用 Django 的事务 API。如果您的特定数据库支持特殊类型的事务(例如,App Engine 上的 run_in_transaction()),您必须使用特定于平台的函数。”

【问题讨论】:

    标签: google-app-engine transactions djangoappengine


    【解决方案1】:

    正如错误消息所暗示的,在 App Engine 上的事务中只允许某些类型的查询 - 特别是应用.ancestor() 过滤器的查询。无法以事务方式执行诸如您尝试执行的查询。

    一种选择是在事务之外执行查询,然后将结果传入。看起来您正在尝试按名称检索分片计数器的特定分片,而这应该可以不使用根本就是一个查询,因为它应该由它的键名来标识。不过,由于我不熟悉 Django 的模型 API,因此我无法建议您如何在 Django 中执行此操作。

    【讨论】:

    • @nailer 带有祖先过滤器的查询很好,因为它们只对单个实体组进行操作。
    • @nailer 不,祖先查询仅返回其父实体是您指定的祖先的实体。这与实体类型无关。
    • @nailer 您应该阅读有关实体、实体组和事务的数据存储文档:code.google.com/appengine/docs/python/datastore/entities.html
    • @nailer 我不是 Django 专家(甚至不是 Django 用户)——您必须询问 Django-nonrel 人员他们是如何公开 App Engine 的 fetch-by-key 功能的。您绝对不需要在这里使用查询。 App Engine 文档有什么“可悲”之处?
    • @nailer 很抱歉,您对我的回答不满意。我提供给文档的参考描述了实体组是什么,这正是您所要求的。正如我刚才所说,我也不熟悉 django-nonrel。如果您想知道如何在 Django-nonrel 中按键获取,您应该查找 django-nonrel 文档,在邮件列表中询问他们,或者在此处发布另一个问题,询问特定问题。
    【解决方案2】:

    Nailer 在他的回答中击中了头部(对不起双关语):DjangoAE 不支持实体组。但是,在这个有进取心的开发者分支 djangoappengine 中有非官方的支持。

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

    补丁尚未完成,但我计划在接下来的几周内试用它并会在此处更新。

    【讨论】:

      【解决方案3】:

      AppEngine WebApp Sharded Counter 示例的 Django 端口,包括常规 Django 对象上的事务,位于:

      https://bitbucket.org/twanschik/sharded-counters-nonrel。查看 sharded_counters/models.py ,其中包括所讨论的单个读/增量/写操作。

      特别是 @commit_locked 装饰器可用于以原子方式读取/写入/递增 Django 模型。

      但请注意,您可以在事务中进行的查询受到限制:Django nonrel, as of Jan 2011, does not support entity groups,这是导致上述错误的原因。

      【讨论】:

        【解决方案4】:

        有一种更优雅的方式可用:

        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)
        

        【讨论】:

          猜你喜欢
          • 2011-06-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-11-30
          • 2014-09-11
          • 1970-01-01
          • 2011-10-20
          • 1970-01-01
          相关资源
          最近更新 更多