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 django-users+unsubscr...@googlegroups.com.
To post to this group, send email to django-users@googlegroups.com.
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