【问题标题】:Update model django through kwargs通过 kwargs 更新模型 django
【发布时间】:2011-05-05 17:28:44
【问题描述】:

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

示例:

obj = Object.objects.create(index=id, **fields)

【问题讨论】:

    标签: python django


    【解决方案1】:

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

    obj = Object(index=id, **fields)
    obj.save()
    

    【讨论】:

    • 您的意思是,如果数据库中没有带索引的字段,它将创建,如果有带该索引的字段,则更新?所以我们可以称之为 update_or_create?
    • 天啊!!!我已经完成了我的 create_or_update 方法...因为我发现在 django 中没有方法 create 或 update 的文章.. 有文章:blog.roseman.org.uk/2010/03/9/easy-create-or-update 所以它的错误文章?
    • 这可能不是我们想要的。它没有更新语义:除了fields 中指定的字段,obj 将被Object 的新实例的默认值覆盖。
    • 只有在指定所有字段时才有效。如果没有,您将使用默认值覆盖...
    • obj中没有填写的数据字段,obj保存的是从数据库中查询的数据。为什么这被标记为答案呢?
    【解决方案2】:
    def update_object(obj, **kwargs):
        for k, v in kwargs.items():
            setattr(obj, k, v)
        obj.save()
    

    【讨论】:

    • 这可能不是 OP 想要的,因为所有字段都将写入数据库;不仅仅是kwargs 中的那些,所以可能会破坏一些东西。 1.5 确实向model.save 引入了update_fields 参数,尽管您必须重复字段名称。
    【解决方案3】:

    你可以得到一个对象的查询集,然后更新这个:

    model = Model.objects.filter(pk=pk)
    model.update(**kwargs)
    

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

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

    话虽如此,我并不知道 Ignacio 的解决方案。我很喜欢。

    【讨论】:

    • 如果您在对 PK 进行过滤时设法获得多条记录,那么您将遇到……更大的问题。不过,过滤为无不是问题,因为发出与任何记录都不匹配的UPDATE 查询是有效的。
    • 是的,我的意思是如果您没有查询 PK,而是查询其他应该是独一无二的。
    【解决方案4】:

    如果您知道要创建它:

    Book.objects.create(**fields)
    

    假设您需要检查现有实例,您可以使用 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()
    

    正如另一个答案中提到的,您还可以在查询集管理器上使用 update 函数,但我相信这不会发出任何信号(如果您不使用它们,这对您来说可能无关紧要)。但是,您可能不应该使用它来更改单个对象:

    Book.objects.filter(id=id).update(**fields)
    

    【讨论】:

    • +1 因为它使用defaultssetattr 来确保将字段的内容应用于对象,而不会丢失可能已经在现有实例上设置的任何其他属性
    【解决方案5】:

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

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

    obj, created = Object.objects.update_or_create(index=id, defaults={**fields})
    

    【讨论】:

      【解决方案6】:

      您可以在filter()查询之后使用方法简单地更新

      obj = Object.objects.filter(index=id).update(**fields) # fields your object(dict) may be **kwargs
      

      如果它是一个 .get() 方法,

      obj = Object.objects.get(index=id)
      obj['key1'] = 'value1'
      obj.save()
      

      【讨论】:

      • 虽然这可能会回答作者的问题,但它缺少一些解释性文字和文档链接。如果没有围绕它的一些短语,原始代码 sn-ps 并不是很有帮助。您可能还会发现how to write a good answer 非常有帮助。请编辑您的答案。
      猜你喜欢
      • 2019-07-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-26
      • 1970-01-01
      • 2017-08-08
      • 2022-01-01
      相关资源
      最近更新 更多