Python AppEngine(或者Django)中是否有名为insert_或_update的快捷方式?为什么不呢?
我多次重复这种模式:(我想这不是很常见吗?) 谷歌应用程序引擎Python AppEngine(或者Django)中是否有名为insert_或_update的快捷方式?为什么不呢?,python,django,google-app-engine,insert-update,Python,Django,Google App Engine,Insert Update,我多次重复这种模式:(我想这不是很常见吗?) 谷歌应用程序引擎 # Insert if object doesn't exist, Otherwise Update Object obj = get_or_insert('123', title='Hello World') obj.title = 'Hello World' obj.puts() Django # Insert if object doesn't exist, Otherwise Update Object obj, crea
# Insert if object doesn't exist, Otherwise Update Object
obj = get_or_insert('123', title='Hello World')
obj.title = 'Hello World'
obj.puts()
Django
# Insert if object doesn't exist, Otherwise Update Object
obj, created = Model.objects.get_or_create(id='123',
defaults={'title':'Hello World'}
if not created:
obj.title = 'Hello World'
obj.save()
如果I可以只需调用insert\u或\u update
,那就好了。不是吗?e、 g:
# AppEngine
obj = insert_or_update('123', title='Hello World')
# Django
obj = Model.objects.insert_or_update(id='123', defaults={'title': 'Hello World'})
更新
回到appengine,我找到了这个get\u或\u insert
方法的代码片段。如下所示:
def txn(key_name, **kwds):
entity = Story.get_by_key_name(key_name, parent=kwds.get('parent'))
if entity is None:
entity = Story(key_name=key_name, **kwds)
entity.put()
return entity
def get_or_insert(key_name, **kwargs):
return db.run_in_transaction(txn, key_name, **kwargs)
get_or_insert('some key', title="The Three Little Pigs")
obj, created = Model.objects.get_or_create(foo='alpha', bar='beta'
defaults={'title':'Hello World'})
我想知道为什么appengine和django中都没有创建insert\u或\u update
方法
应用程序引擎解决方案
Django溶液
如果我正确理解了问题:
obj, created = Model.objects.get_or_create(id='123',
defaults={'title':'Hello World'})
上述内容应替换为以下内容:
def txn(key_name, **kwds):
entity = Story.get_by_key_name(key_name, parent=kwds.get('parent'))
if entity is None:
entity = Story(key_name=key_name, **kwds)
entity.put()
return entity
def get_or_insert(key_name, **kwargs):
return db.run_in_transaction(txn, key_name, **kwargs)
get_or_insert('some key', title="The Three Little Pigs")
obj, created = Model.objects.get_or_create(foo='alpha', bar='beta'
defaults={'title':'Hello World'})
其中foo和bar是模型中的字段。这解决了django的重复问题。对appengine不确定。这可能不像你想象的那么普遍。就我个人而言,我发现自己不必经常这样做,而且当我这样做时,它只比您建议的
insert\u或\u update
方法长两三行,这还不足以让我大声呼喊这个特性,也不足以激励我自己添加它。尽管过去我在重复密钥更新中使用了MySQL的INSERT…
我自己也有过几次这样的经历,就在几周前,我还在想为什么Django在M2M关系上没有一个toggle
方法……我最后做了一个:
编辑
Django 1.7看起来将具有这个“UPSERT”功能,Django
(来自Django官方文件)
Django 1.7版本中的新增功能
使用给定的kwargs
更新对象的便捷方法,必要时创建新对象。默认值
是用于更新对象的(字段、值)对字典
返回(object,created)
的元组,其中object
是已创建或更新的对象,created
是指定是否创建新对象的布尔值
update\u或\u create
方法尝试根据给定的kwargs
从数据库中获取对象。如果找到匹配项,它将更新在默认值
字典中传递的字段
这是通往样板代码的捷径。例如:
try:
obj = Person.objects.get(first_name='John', last_name='Lennon')
for key, value in updated_values.iteritems():
setattr(obj, key, value)
obj.save()
except Person.DoesNotExist:
updated_values.update({'first_name': 'John', 'last_name': 'Lennon'})
obj = Person(**updated_values)
obj.save()
随着模型中字段数量的增加,这种模式变得相当笨拙。可以使用update\u或\u create()
重写上述示例,如下所示:
obj, created = Person.objects.update_or_create(
first_name='John', last_name='Lennon', defaults=updated_values)
有关如何解析kwargs中传递的名称的详细说明,请参阅
如上文中所述,此方法容易出现争用情况,如果不在数据库级别强制执行唯一性,则可能导致同时插入多行
阿彭金
还没有那么幸运,正如Matt之前提到的,它可能不是一个常见的用例。也许在AppEngine中,这种用例并不多 对不起,我想你误解了我的问题。使用当前的答案,您将获得所提供参数的对象。object.title可能不是Hello World,因此我还想用标题Hello World更新该对象。因此,如果您已经拥有该对象,请将标题更新为Hello World。如果没有对象,请创建标题为Hello World的对象。将其放在一行快捷方式方法中,即Model.objects.insert_或_update(foo='alpha',bar='beta',defaults={'title':'Hello World'});但我在想,为什么没有这样的方法,这不是常见的用例吗?#您的代码需要一些额外的行,才能按照我的要求工作。;如果不是obj:obj.title=“Hello World;obj.save();嗯……这是有道理的,……无论如何,这是M2M的一个有趣的切换功能。+1:-你说的是一个返回我相信的值的UPSERT操作。Django完全不支持这样的函数。最近有一个提交与这个问题有关,@MattDeacalionStevens,最后。那将在Django 1.7上,:-)是的……一个whi我还想去,但你说得对。:-)