As a followup to the suggestion of MyModel.objects.filter(money__gte =
value, pk = self.pk).update(F...)

Here's an example:

We have testapp/models.py:

from django.db import models
class TestModel(models.Model):
    balance =  models.IntegerField()


>>> from django.db.models import F
>>> TestModel.objects.create(balance = 5) #Pk will be 1 I just create one.
>>> import logging
>>> l = logging.getLogger('django.db.backends')
>>> l.setLevel(logging.DEBUG)
>>> l.addHandler(logging.StreamHandler())
>>> TestModel.objects.filter(balance__gte = 4, pk = 1).update(balance =
F('balance') - 4)
(0.001) UPDATE "testapp_testmodel" SET "balance" =
"testapp_testmodel"."balance" - 4 WHERE ("testapp_testmodel"."balance" >= 4
 AND "testapp_testmodel"."id" = 1 ); args=(4, 4, 1)
1
>>> TestModel.objects.filter(balance__gte = 4, pk = 1).update(balance =
F('balance') - 4)
(0.000) UPDATE "testapp_testmodel" SET "balance" =
"testapp_testmodel"."balance" - 4 WHERE ("testapp_testmodel"."balance" >= 4
 AND "testapp_testmodel"."id" = 1 ); args=(4, 4, 1)
0



*So this seems to generate a single SQL statement.*
*
*
*I'm not totally familiar with database administration though, so as** Melvyn
rightly pointed out, it's always better if you can get the extra security
of having an SQL constraint into your dabatase and wrap your queries in a
transaction (as you'll probably be adding a line to the statement if the
withdrawal succeeds).*
*
*

2012/8/20 Thomas Orozco <g.orozco.tho...@gmail.com>

> A few suggestions :
>
> Circumvent the problem with smarter design: don't store the money on the
> object, make the user's money the sum of all their transactions (credit -
> debit).
> You get lesser performance, but you also get history!
>
> Maybe you could try (not sure about that):
>
> MyModel.objects.filter(money__gte = value, pk = self.pk).update(F...)
>
> and inspect the return value (number of updated rows!).
> Now, you'd need to make sure django does that in a single statement.
>
> If that doesn't work, I think update is the way to go anyway, but it might
> get a bit messy.
>
> F... is an F object whose syntax I don't have off the top of my head.
> Le 20 août 2012 18:54, "Sebastien Flory" <sfl...@gmail.com> a écrit :
>
> Hi everyone,
>>
>> I'm looking for the proper django way to do an update of an attribute on
>> my model instance, but only if the attribute current value is checked
>> agains't a condition, in an atomic way, something like this:
>>
>> def use_money(self, value):
>>   begin_transaction()
>>   real_money = F('money')
>>   if real_money >= value:
>>     self.money = F('money') - value
>>     self.save()
>>   end_transaction()
>>
>> I want to make sure that I avoid race condition so money never goes below
>> 0.
>>
>> Can you help me out?
>>
>> Thanks,
>>
>> Sebastien
>>
>> --
>> You received this message because you are subscribed to the Google Groups
>> "Django users" group.
>> To view this discussion on the web visit
>> https://groups.google.com/d/msg/django-users/-/hr1fBuAcX3kJ.
>> To post to this group, send email to django-users@googlegroups.com.
>> To unsubscribe from this group, send email to
>> django-users+unsubscr...@googlegroups.com.
>> For more options, visit this group at
>> http://groups.google.com/group/django-users?hl=en.
>>
>

-- 
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To post to this group, send email to django-users@googlegroups.com.
To unsubscribe from this group, send email to 
django-users+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-users?hl=en.

Reply via email to