【问题标题】:Django equivalent of SQL REPLACEDjango 相当于 SQL REPLACE
【发布时间】:2011-04-10 11:51:39
【问题描述】:

此 SQL 是否有 Django ORM 最佳实践:

REPLACE app_model SET field_1 = 'some val', field_2 = 'some val';

假设:field_1 或 field_2 将有一个唯一的键(或在我的情况下两者都有),否则这将始终评估为 INSERT。

编辑:

我现在最好的个人答案是这个,但应该是 2-3 个查询,其中 1 个应该是可能的:

    from django.core.exceptions import ValidationError
    try:
        Model(field_1='some val',field_2='some val').validate_unique()
        Model(field_1='some val',field_2='some val',extra_field='some val').save()
    except ValidationError:
        Model.objects.filter(field_1='some val',field_2='some val').update(extra_field='some val')

【问题讨论】:

    标签: django django-orm


    【解决方案1】:

    你说你想要REPLACE,我相信它应该在插入之前删除任何现有的行,但你的例子表明你想要更像UPSERT的东西。

    AFAIK,django 不支持REPLACE(或sqlite 的INSERT OR REPLACE,或UPSERT)。但是您的代码可以合并:

    obj, created = Model.objects.get_or_create(field_1='some val', field_2='some_val')
    obj.extra_field = 'some_val'
    obj.save()
    

    这当然假设 field_1field_2 或两者都是唯一的(如您所说)。

    这仍然是两个查询(SELECT 用于get_or_createINSERTUPDATE 用于save),但直到出现类似UPSERT 的解决方案(它可能不会用于很长很长时间),这可能是你能做的最好的了。

    【讨论】:

    • 如果你想更新很多字段,那个方法会给出丑陋的代码,但我想不出更好的(更紧凑)
    【解决方案2】:

    从 Django 1.7 开始你可以使用update_or_create 方法:

    obj, created = Person.objects.update_or_create(
        first_name='John',
        last_name='Lennon',
        defaults={'profession': 'musician'},
    )
    

    【讨论】:

    • 如果属性之一被定义为unique=True,则会抛出IntegrityError
    【解决方案3】:

    我认为下面的效率更高。

    (obj, created) = Model.objects.get_or_create(
       field_1 = 'some val',
       field_2 = 'some_val',
       defaults = {
          'extra_field': 'some_val'
       },
    )
    if not created and obj.extra_field != 'some_val':
       obj.extra_field = 'some_val'
       obj.save(
          update_fields = [
             'extra_field',
          ],
       )
    

    这只会在行未创建且需要更新时更新 extra_field。

    【讨论】:

    • 这是更好的答案...... Django 至少从 1.3 开始就有 defaults 参数(我仍然可以在网上找到最旧的文档)。顺便说一句,您不需要 (obj, created) 周围的括号 :)
    • @Anentropic 是的,我知道我的代码强迫症很糟糕,出于某种原因,我更喜欢它,但在过去的一年里,我采用了大部分 PEP8 格式化标准,在某种程度上 PEP8 正在启用/现在让我的代码更加强迫症!
    • 我知道,我也遇到过同样的情况:)
    猜你喜欢
    • 2010-09-14
    • 2013-03-20
    • 2021-08-29
    • 2011-10-14
    • 2015-09-21
    • 2015-12-23
    • 2011-07-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多