title: Django - Postgresql: transaction and concurrency
body: <p>There is a lot of topics on Django concurrency, but after checking a lot of those, I don't feel I have found my answer when it comes to transactions.</p>
  
  <p>Django version 1.3.1. Postgresql version 8.4.7.</p>
  
  <p>A very simple version of my models could look like this:</p>
  
  <pre><code>def Member(Model):
    money = PositiveIntegerField(default=0)
    user = OneToOneField(User, related_name='member', primary_key=True)
  
  def Bet(Model):
    total_money = PositiveIntegerField(default=0)
  </code></pre>
  
  <p>I also have a table Money which is a relation between Member and Bet. It's not directly linked to my problem but it helps me monitor it, because it can't be impacted by any concurrency issues. i.e I just have to count my table Money to test if the fields money of Member and total_money of Bet are correct.</p>
  
  <p>I can't rely only on the table Money though, and I need my fields to be correct, because I filter a lot using them.</p>
  
  <p>My first try for the bet function was something like this (just with a lot more modifications to a lot more tables).</p>
  
  <pre><code>def bid(user_pk, bet_pk, value):
    #create Money object
    member = User.objects.get(user_pk).member
    member.money = F('money') - value
    member.save()
    bet = Bet.objects.get(bet_pk)
    bet.total_money = F('total_money') + value
    bet.save()
  </code></pre>
  
  <p>This version was working just fine until I get my first crash during one transaction.
  I had also to copy paste all the tests from my clean() functions in bid(), because I'm not really able to use clean() or full_clean() in this case (especially if bet raises, after member is saved).</p>
  
  <p>So I decided to give a try to django transaction.</p>
  
  <pre><code>@transaction.commit_manually
  def bid(user_pk, bet_pk, value):
    try:
      #create money object
      member = User.objects.get(user_pk).member
      member.money -= value
      member.clean()
      member.save()
      bet = Bet.objects.get(bet_pk)
      bet.total_money += value
      bet.clean()
      bet.save()
    except:
      transaction.rollback()
      raise
    else:
      transaction.commit()
  </code></pre>
  
  <p>But without the possibility to use F() object inside of manual transaction (which makes sense). I ended up with a lot of concurrency issues.</p>
  
  <p>I see only two solutions:</p>
  
  <ul>
  <li><p>Only create Money objects during the bid()/transaction, then have an asynchronous worker (Celery ?) that updates the related fields in Member and Bet.</p></li>
  <li><p>Create a list of bid()/transaction (Redis ?), and make all transactions that modify money related fields synchronous.</p></li>
  </ul>
  
  <p>Am I missing an obvious and easier solution ?
  If not, what solution would you recommend using which technology ?</p>