【问题标题】:Django ORM query: how to swap value of a attribute?Django ORM查询:如何交换属性的值?
【发布时间】:2014-02-10 12:43:35
【问题描述】:

情况就是这样。我想交换用户的价值。

user_with_apple = User.objects.filter(fruit=apple)
user_with_pear = User.objects.filter(fruit=pear)

user_with_apple.update(fruit=pear)
user_with_pear.update(fruit=apple)

好吧,这行不通,因为一切都以梨结束。因为 django ORM 很懒,我想?

请问我该如何执行这样的“交换”操作?我必须使用中间值吗?

非常感谢!

或者如果我通过切片或调用 list() 来强制评估查询是否有意义? 例如。 user_with_apple = User.objects.filter(fruit=apple)[:] user_with_pear = User.objects.filter(fruit=pear)[:]

【问题讨论】:

    标签: python django orm django-queryset


    【解决方案1】:

    这就是我想到的:

    如果你在 QuerySet 上调用 list,你会强制 Django 给你对象。这样做的问题是您不能在列表上调用update,因此您需要遍历列表并更新每个对象。

    这可能对您有所帮助:

    users_with_apple = list(User.objects.filter(fruit=apple))
    users_with_pear = list(User.objects.filter(fruit=pear))
    
    for user in users_with_apple:
        user.fruit = pear
        user.save()
    for user in users_with_pear:
        user.fruit = apple
        user.save()
    

    【讨论】:

    • 嘿,谢谢你的回答!我认为它会起作用。但在那种情况下,我都必须分别对它们中的每一个调用 .save() 对吗?这是否意味着我必须经常访问数据库? @Steinar
    • 这可能是正确的。我不认为这会产生额外的数据库调用。
    • @noooooooob 是的,每次你打电话给save() db do update
    • @DoNotArrestMe 这和使用update有区别吗?
    • @DoNotArrestMe 我不认为我可以在切片或调用 list() 后使用 update() :(
    【解决方案2】:

    变体 1

    我想你有CharField 对应fruit。然后在选项中添加unknown 选项。

    FRUIT_CHOICES = (
        ...
        (unknown, 'Unknown'),
        (apple, 'Apple'),
        (pear, 'Pear'),
        ...
    )
    
    class User(models.Model):
        ...
        fruit = models.CharField(..., choices=FRUIT_CHOICES)
        ...
    

    那就试试这个吧。

    User.objects.filter(fruit=apple).update(fruit=unknown)
    User.objects.filter(fruit=pear).update(fruit=apple)
    User.objects.filter(fruit=unknown).update(fruit=pear)
    

    变体 2

    fruit 字段添加访问空值。

    FRUIT_CHOICES = (
        ...
        (apple, 'Apple'),
        (pear, 'Pear'),
        ...
    )
    
    class User(models.Model):
        ...
        fruit = models.CharField(..., blank=True, null=True, choices=FRUIT_CHOICES)
        ...
    
    User.objects.filter(fruit=apple).update(fruit=None)
    User.objects.filter(fruit=pear).update(fruit=apple)
    User.objects.filter(fruit=None).update(fruit=pear)
    

    【讨论】:

    • 感谢您的回答! @DoNotArrestMe!这感觉就像经典的“切换 2 整数的值”解决方案,只命中 db 3 次。嗯,试试看。
    • @noooooooob 欢迎您!是的。如果您需要性能 - 这只是对 django orm 后面的 db 的 3 update 查询。
    • 太糟糕的水果在我的情况下不能是 None ?
    • @noooooooob 好吧,将其设置为(不在您的数据库中)以外的其他值,例如FooBar
    • @noooooooob 水果田有什么类型?
    猜你喜欢
    • 2019-10-17
    • 2016-03-25
    • 1970-01-01
    • 2017-04-12
    • 2016-06-04
    • 2016-04-20
    • 2021-07-06
    • 2016-12-17
    • 2014-12-26
    相关资源
    最近更新 更多