【问题标题】:Conditional update_or_create with django使用 django 进行条件 update_or_create
【发布时间】:2018-10-11 07:25:27
【问题描述】:

测试模型

class Room(models.Model):
    """
    This stores details of rooms available
    """
    name = models.CharField(
        null=False,
        blank=False,
        max_length=100,
        help_text='Enter the name of the room'
    )
    capacity = models.PositiveIntegerField(
        null=False,
        blank=False,
        help_text='Enter the number of person\'s the room can accommodate'
    )
    created_at = models.DateTimeField(auto_now_add=True)
    modified_at = models.DateTimeField(auto_now=True)

如果模型存在并且它的 modified_at 时间小于 x 时间,我想更新模型,否则只需创建模型。 作为参考,这里是我希望 django 执行的原始 sql。

INSERT INTO room VALUES (1,'2018-04-30 18:15:32.96468+04:30','2018-04-30 18:15:32.96468+04:30','Room-A',30) ON CONFLICT(id) DO UPDATE SET capacity=10 WHERE room.modified_at < '2017-04-30 18:15:32.96468+04:30';

我也想知道我写的 SQL 查询是否是原子的

【问题讨论】:

    标签: django postgresql sql-update


    【解决方案1】:

    以下示例可能会正常工作

    第一个选项

    try:
        obj = Room.objects.get(
            id=id, # test with other fields if you want
        )
        if obj.modified_at < DATETIME:
            obj.capacity = 10
            obj.save()
        else:
            obj = Room.objects.create(
                # fields attributes
            )
    except Room.DoesNotExist:
        obj = Room.objects.create(
            # fields attributes
        )
    

    第二个选项

    或者你可以使用 django 的 Conditional Expression 来这样做

    from django.db.models import F, Case, When
    import datetime
    
    your_date = datetime.datetime.now()
    condition = Case(When(modified_at__lt=your_date,then=10),default=F('capacity'))
    
    • 我们检查modified_at是否小于your_date
    • 那么这个条件的值为10,
    • 否则,我们保持与F('capacity')相同的字段值

    其余代码

    Room.objects.update_or_create(name='new_name',
               defaults={'name':'new_name','capacity':conditition})
    

    【讨论】:

    • 此代码容易受到竞争条件的影响。我们可以将此代码放在原子事务块中,但我只是想知道是否有更好的方法
    • 我编辑了我的答案,添加了另一种方法,这个更有效@user9724623
    • 这太棒了@Lemayzeur,但是我必须为模型中的每个属性添加条件,而不是我想批量更新,即如果条件满足则更新每个属性或保持原样。请查看我上面的查询,以便更清楚地了解我的意思
    • 所以你不需要使用update_or_create,而是queryset.update()它会做你想做的事
    • 但如果该行不存在,它不会创建,我想要 - 如果行退出,那么只有在时间条件满足时才更新,否则创建一个新行
    猜你喜欢
    • 2021-02-16
    • 1970-01-01
    • 1970-01-01
    • 2018-08-15
    • 2018-10-03
    • 1970-01-01
    • 2017-11-27
    • 2021-05-09
    • 1970-01-01
    相关资源
    最近更新 更多