0

This question is similar to Atomic operations in Django? however for Django 1.4. I'm wondering if there is a way to do this without resorting to "raw SQL". My setup is a little different then his so I'll explain.

I have a record for a User and a generic table called UserRecords. Here's the definition for UserRecord.

class UserRecord (models.Model):
    """
    User record model for :class:`User` users to keep
    aux data like services connected, latest stats, and other accounts.
    """

    def __unicode__ (self):
        return u"{0}.{1}.{2}.{3}".format(self.user, self.parent, self.key, self.value)

    def update_maybe_save (self, val):
        if self.value != val:
            self.value = val
            self.save()

    #: :class`User` who owns this record
    user = models.ForeignKey("User")
    parent = models.CharField(max_length=255, blank=True, null=True, db_index=True)
    key = models.CharField(max_length=255, db_index=True)
    value = models.TextField(blank=True, null=True)

As you can see, it's a very generic k/v store table with the optional parent attribute that's useful for grouping records together and optimizing some searches. It's very useful when, in this case, we want to add a couple alias's for a user.

# Inside the User model
def add_alias (self, name):
    try:
        UserRecord.objects.get(user=self, parent="alias", key=name, value=self.username)
    except UserRecord.DoesNotExist:
        UserRecord(user=self, parent="alias", key=name, value=self.username).save()

This sets ourselves up for a race condition where if a user enters the same alias twice it could create two identical records. Then each UserRecord.objects.get call fails because there are two, I get a Django error email, and I manually go fix the database.

I can't find anything in the documentation that allows me to create something atomically. Any ideas apart from the raw sql mentioned in the other question?

Community
  • 1
  • 1
Josh K
  • 28,364
  • 20
  • 86
  • 132
  • Maybe use `unique_together = (("user", "key"),)` https://docs.djangoproject.com/en/dev/ref/models/options/#unique-together – sneawo Jan 15 '13 at 20:12
  • @sneawo Was going to say *nope* but lemme check on that – Josh K Jan 16 '13 at 01:39
  • @sneawo Ah, got it. I have some parent/key values that are used as a many store. So parent="likes", key="brands", value=[name of brand]. – Josh K Jan 16 '13 at 01:43
  • What if `unique_together = (("user", "parent", "key", "value"),)`? – sneawo Jan 16 '13 at 08:13
  • @sneawo Kinda defeats the purpose, because this doesn't prevent duplicates under the conditions where I *do* only want one record – Josh K Jan 16 '13 at 15:15

0 Answers0