通过kwargs更新模型django

Pol*_*Pol 19 python django

如何传递包含字段的dict来更新Django模型?这不是创建对象,而是更新它.

例:

obj = Object.objects.create(index=id, **fields)
Run Code Online (Sandbox Code Playgroud)

Ign*_*ams 27

只要PK相同,就会覆盖现有的行.

obj = Object(index=id, **fields)
obj.save()
Run Code Online (Sandbox Code Playgroud)

  • 这可能不是想要的.它没有更新语义:除了`fields`中指定的字段外,`obj`将覆盖新的`Object`实例的默认值. (6认同)
  • 仅在指定了所有字段的情况下才起作用。如果没有,您将覆盖默认值... (2认同)

Ned*_*der 15

def update_object(obj, **kwargs):
    for k, v in kwargs.items():
        setattr(obj, k, v)
    obj.save()
Run Code Online (Sandbox Code Playgroud)

  • 这可能不是OP想要的,因为所有字段都将被写入数据库; 不只是那些"kwargs",所以可能是破坏性的东西.1.5确实为`model.save`引入了`update_fields`参数,尽管你必须重复字段名称. (3认同)

Mat*_*kel 10

您可以获取一个对象的查询集,然后更新:

model = Model.objects.filter(pk=pk)
model.update(**kwargs)
Run Code Online (Sandbox Code Playgroud)

但是,这不会调用对象上的.save()方法.不过,我认为它只会进行一次数据库查询.

请注意,如果您没有过滤到一个对象(即查询得到多个对象:例如,如果您没有查询PK),它将更新所有对象.如果它过滤为none,则不会将任何内容写入数据库.

话虽如此,我还没有意识到Ignacio的解决方案.我非常喜欢.


lee*_*ech 6

如果您知道要创建它:

Book.objects.create(**fields)
Run Code Online (Sandbox Code Playgroud)

假设您需要检查现有实例,则可以使用get或create找到它:

instance, created = Book.objects.get_or_create(slug=slug, defaults=fields)
if not created:
    for attr, value in fields.iteritems(): 
        setattr(instance, attr, value)
    instance.save()
Run Code Online (Sandbox Code Playgroud)

如另一个答案中所述,您也可以update在queryset Manager上使用该函数,但我相信不会发送任何信号(如果您不使用它们,则对您而言可能并不重要)。但是,您可能不应该使用它来更改单个对象:

Book.objects.filter(id=id).update(**fields)
Run Code Online (Sandbox Code Playgroud)


Chi*_*idG 5

这个问题有点老了,但是只是为了使它与Django的最新发展保持同步-从1.7开始,存在一个查询集update_or_create方法,其工作方式与相似get_or_create

在这种情况下,它可以像这样使用:

obj, created = Object.objects.update_or_create(index=id, defaults=fields)
Run Code Online (Sandbox Code Playgroud)