noooooooob
noooooooob

Reputation: 1890

Django ORM query: how to swap value of a attribute?

Here is the case. I want to swap value of user.

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)

Well, this does not work, as everything ends up with pear. Because django ORM is lazy, I suppose?

So may I ask how can I perform such a "swap" operation? Do I have to use a intermediate value?

Thank you so much!

Or does it make sense if I force the evaluation of the query by slicing or calling list() on it? eg. user_with_apple = User.objects.filter(fruit=apple)[:] user_with_pear = User.objects.filter(fruit=pear)[:]

Upvotes: 0

Views: 896

Answers (2)

Steinar Lima
Steinar Lima

Reputation: 7821

Here is what that comes to mind:

If you call list on your QuerySets, you force Django to give you the objects. The problem with this is that you can't call update on a list, so you need to iterate over the lists, and update each object.

This may help you on your way:

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()

Upvotes: 1

DoNotArrestMe
DoNotArrestMe

Reputation: 1279

Variant 1

I suppose you have CharField for fruit. Then add unknown option to choice.

FRUIT_CHOICES = (
    ...
    (unknown, 'Unknown'),
    (apple, 'Apple'),
    (pear, 'Pear'),
    ...
)

class User(models.Model):
    ...
    fruit = models.CharField(..., choices=FRUIT_CHOICES)
    ...

Then try this.

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

Variant 2

Add access null values for fruit field.

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)

Upvotes: 1

Related Questions