トランザクションを使用して問題を解決できると思います。適切な django のドキュメントは次のとおりです。例を次に示します。
2 つの同時トランザクションが同じ sqlite DB に書き込もうとすると、「OperationalError: database is locked」がスローされるようです。おそらく Django ORM (リンクを参照) を使用したいと思うでしょうが、アイデアを示すためのハックな例を次に示します。
import sqlite3
# 2 connections, 2 cursors
con = sqlite3.connect('test.db', isolation_level=None)
con2 = sqlite3.connect('test.db', isolation_level=None)
cur = con.cursor()
cur2 = con2.cursor()
# create really simple table
try:
cur.execute("CREATE TABLE MOVIES(id INTEGER PRIMARY KEY, r1 INTEGER, r2 INTEGER)")
cur.execute("INSERT INTO MOVIES(id,r1, r2) VALUES (1,0,0)")
cur.execute("INSERT INTO MOVIES(id,r1, r2) VALUES (2,0,0)")
except:
pass
# awkward read/write split mid-transaction is purely for demonstration purposes..
def read(cursor):
cursor.execute("BEGIN IMMEDIATE TRANSACTION") # get write lock straight away
data = cursor.execute("SELECT * FROM MOVIES WHERE r1 == 0 OR r2 == 0")
return data.fetchall()
def write(cursor, movie_id, reviewer_column, new_reviewer_id):
cursor.execute("UPDATE MOVIES SET %s=%d WHERE id == %d AND %s ==0" % (
reviewer_column, new_reviewer_id, movie_id, reviewer_column))
cursor.execute("COMMIT")
# works fine
data1 = read(cur) # [(1, 0, 0), (2, 0, 0)]
write(cur, data1[0][0], "r1", 123)
# now we have concurrent access..
data1 = read(cur) # [(1, 123, 0), (2, 0, 0)]
data2 = read(cur2) # throws OperationalError: database is locked.
# the second thread should probably wait a bit before retrying.
# in the mean time..
write(cur, data1[0][0], "r2", 456) #works
# now it's safe for the second thread to retry
data2 = read(cur2) # [(2, 0, 0)]
write(cur2, data2[0][0], "r1", 457) #works
上記の後のデータ:
# MOVIES
# id | r1 | r2
# 1 | 123 | 456
# 2 | 457 | 0
これにより、DB に意味のないものを配置することはできなくなりますが、即時書き込みロックは、そこに到達するためのやや粗雑な方法です。