Dear Django group,

please consider this code:


    from datetime import date
    from django.db import models


    class TestModel(models.Model):
        jahr = models.SmallIntegerField()
        monat = models.SmallIntegerField()
        some_value = models.SmallIntegerField()

        class Meta:
            unique_together = ('jahr', 'monat')


    def demonstrate_the_problem():
        d = date.today()

        try:
            t = TestModel.objects.get(jahr=d.year, monat=d.month)
            # t exists, no need to create or modify it.
            return t.some_value
        except TestModel.DoesNotExist:
            # t did not yet exist, so we have to create it anew.
            # Note that there is a "unique together" constraint in place
            # that makes sure that the tuple (jahr, monat) only exists once.
            # Thus we create a new instance, then lock it with
            # select_for_update()  --  but this is still not atomic!
            TestModel(jahr=d.year, monat=d.month).save()
            t = TestModel.objects.get(
                    jahr=d.year, monat=d.month).select_for_update()

        # A long computation, eventually setting fields in the new t,
        # then saving it for the next call to this function.
        t.some_value = 123
        t.save()
        return t.some_value


The problem is that another thread too may have created a TestModel with the same (jahr, monat) in the timespan between our "does not exist" and "lock", triggering a violation of the "unique" constraint.

Thus, the question is how we can make the sequence "does not exist – create anew – lock" atomic?

Any feedback would very much be appreciated!

Many thanks and best regards,
Carsten

--
You received this message because you are subscribed to the Google Groups "Django 
users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-users/5733370C.2050001%40cafu.de.
For more options, visit https://groups.google.com/d/optout.

Reply via email to