【问题标题】:How to select a record and update it, with a single queryset in Django?如何在 Django 中使用单个查询集选择记录并更新它?
【发布时间】:2011-02-12 08:24:46
【问题描述】:

如何在同一个 queryset 上运行 updateselect 语句,而不必执行两个查询: - 一个选择对象 - 和一个更新对象

SQL 中的等价物是这样的:

update my_table set field_1 = 'some value' where pk_field = some_value

【问题讨论】:

    标签: sql django django-models orm django-queryset


    【解决方案1】:

    使用查询集object update method

    MyModel.objects.filter(pk=some_value).update(field1='some value')
    

    【讨论】:

    • 只是一个公平的警告......如果您使用这样的update 方法,那么附加到该模型或其他“代码内容”的任何信号都不会针对对象运行。只是来自被烧毁的人的指示:)
    • @DMactheDestroyer 老兄感谢您提供的宝贵信息。那么我们应该使用旧的更新方式吗? (即)获取并保存?
    • @learning 好兄弟,这完全取决于你的情况。 update 方法非常适合大规模更新,但当您使用它时,它应该会在您的脑海中引发警告,您需要查看附加到该对象的任何可能还需要手动触发的信号
    • 是否可以在更新函数中访问当前模型实例?喜欢MyModel.objects.filter(pk=some_value).update(field1=self.data)
    • @DipakChandranP 你应该问一个新问题,而不是把 cmets 放在一个六岁的孩子身上。但是 F() 表达式可能是你想要的。
    【解决方案2】:

    Django 数据库对象使用相同的 save() 方法来创建和更改对象。

    obj = Product.objects.get(pk=pk)
    obj.name = "some_new_value"
    obj.save()
    

    Django 如何知道 UPDATE 与 INSERT
    如果对象的主键属性设置为计算结果为 True 的值(即,值 除了 None 或空字符串),Django 执行更新。如果 对象的主键属性未设置或 UPDATE 未设置 更新任何东西,Django 执行一个 INSERT。

    参考:https://docs.djangoproject.com/en/1.9/ref/models/instances/

    【讨论】:

      【解决方案3】:

      这个答案比较了上述两种方法。 如果您想在一行中更新多个对象,请选择:

      # Approach 1
      MyModel.objects.filter(field1='Computer').update(field2='cool')
      

      否则您将不得不遍历查询集并更新单个对象:

      #Approach 2    
      objects = MyModel.objects.filter(field1='Computer')
      for obj in objects:
          obj.field2 = 'cool'
          obj.save()
      
      1. 方法 1 更快,因为它只进行一次数据库查询,而方法 2 进行“n+1”个数据库查询。 (对于查询集中的 n 项)

      2. 第一种方法进行一次数据库查询,即 UPDATE,第二种方法进行两次:SELECT 和 UPDATE。

      3. 权衡的是,假设您有任何触发器,例如更新 updated_on 或任何此类相关字段,它不会在直接更新时触发,即方法 1。

      4. 方法 1 用于查询集,因此可以一次更新多个对象,而不是方法 2。

      【讨论】:

      • 关于 1. - 我认为查询结果在第一次调用查询时被缓存,因此实​​际上仍然只有一次调用 DB。
      【解决方案4】:

      第一种方法

      MyTable.objects.filter(pk=some_value).update(field1='some value')
      

      第二种方法

      q = MyModel.objects.get(pk=some_value)
      q.field1 = 'some value'
      q.save()
      

      第三种方法

      通过使用get_object_or_404

      q = get_object_or_404(MyModel,pk=some_value)
      q.field1 = 'some value'
      q.save()
      

      第四种方法

      如果您需要 pk=some_value 存在则 update 否则 create 使用 update_or_create 新建一个。

      MyModel.objects.update_or_create(pk=some_value,defaults={'field1':'some value'})
      

      【讨论】:

        【解决方案5】:

        只有在serializer的情况下,你才能用很简单的方式更新!

        my_model_serializer = MyModelSerializer(
            instance=my_model, data=validated_data)
        if my_model_serializer.is_valid():
        
            my_model_serializer.save()
        

        仅在 form 的情况下!

        instance = get_object_or_404(MyModel, id=id)
        form = MyForm(request.POST or None, instance=instance)
        if form.is_valid():
            form.save()
        

        【讨论】:

        • 我认为序列化程序来自 Djanog Rest Framework,而不是 Django。
        • 是的,但是 Django form 来自 Django Proper。
        【解决方案6】:

        如果您需要根据旧字段值设置新值,请执行以下操作:

        update my_table set field_1 = field_1 + 1 where pk_field = some_value
        

        使用query expressions:

        MyModel.objects.filter(pk=some_value).update(field1=F('field1') + 1)
        

        这将自动执行更新,即使用一个对数据库的更新请求而不先读取它。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-07-15
          • 1970-01-01
          • 2021-12-29
          相关资源
          最近更新 更多