orm - Atomic conditional-update in Django -


so have 2 models:

class unit(models.model):    name = models.charfield()  class session(models.model):    unit = models.foreignkey(unit)    startdatetime = models.datetimefield()    enddatetime = models.datetimefield()  

users can book 'units' sessions start , end @ user-requested date/time. no unit can in use @ same time , i'd enforce ensuring no overlapping sessions per unit can booked. i'd 1 underlying query if possible, presumably guaranteeing atomicity of update?

i've come 2 approaches, neither of i'm happy with:

executing raw sql:

insert "myapp_session" user_id, unit_id, startdatetime, enddatetime  select 6, 2, '2013-05-18 02:09:02', '2013-05-18 03:09:02' "myapp_session"  not exists  (select * "myapp_session" unit_id=2 , ("startdatetime" between '2013-05-18 02:09:02' , '2013-05-18 03:09:02' or "enddatetime" between '2013-05-18 02:09:02' , '2013-05-18 03:09:02')); 

this should insert new session if there none booked overlap it. possible orm similar?

the other approach use select_for_update() on unit, using lock.

unitlock = list(unit.select_for_update().filter(id=2)) # list() forces evaluation, should block others until have finished inserting session? overlappingsessions = session.objects.filter(startdatetime__range=[requestedstart, requestedend], enddatetime__range=[requestedstart, requestedend]) if not overlappingsessions.exists():     session.objects.create(unit=2, startdatetime=requestedstart, enddatetime=requestedend) # lock should freed view function returns 

this locks 1 row in units table, other sessions other units can still added concurrently.

another related approach might add 'sessioninsertinprogress' field unit. assuming updated atomically, stop other concurrent processes continuing inserting session on unit while allowing sessions booked other units unimpeded.


Comments

Popular posts from this blog

SPSS keyboard combination alters encoding -

Add new record to the table by click on the button in Microsoft Access -

javascript - jQuery .height() return 0 when visible but non-0 when hidden -