[英]Django/sqlite3 “OperationalError: no such table” on threaded operation
By everything I read in the docs, both Django and py-sqlite3 should be fine with threaded access. 根据我在文档中阅读的所有内容,Django和py-sqlite3都可以使用线程访问。 (Right?) But this code snippet fails for me. (对吗?)但是这个代码片段对我来说失败了。 The operations in the main thread work, but not in the thread(s) I create. 主线程中的操作有效,但我创建的线程中的操作无效。 There I get: 我得到:
File "C:\\Python27\\lib\\site-packages\\django-1.9-py2.7.egg\\django\\db\\backends\\sq lite3\\base.py", line 323, in execute return Database.Cursor.execute(self, query, params) 在执行返回Database.Cursor.execute(self ,查询,参数)
OperationalError: no such table : thrtest_mymodel OperationalError:没有这样的表 :thrtest_mymodel
What's the problem? 有什么问题?
How do I go about tracking down exactly what's happening to patch Django or whatever's necessary to fix it? 我该如何准确跟踪修补Django的情况或修复它的必要条件? The point of failure in Django is pretty indimidating. Django的失败点非常严重。 I can't tell how to see what tables it DOES see, or what differences to look for between main and other threads. 我无法告诉您如何查看它看到的表,或者在主线程和其他线程之间寻找什么区别。
from django.db import models
# Super-simple model
class MyModel(models.Model):
message = models.CharField('Message', max_length=200, blank=True)
#Test
from django.test import TestCase
import time
import threading
import random
done = threading.Event()
nThreads = 1
def InsertRec(msg):
rec = MyModel.objects.create(message=msg)
rec.save()
def InsertThread():
try:
msgNum = 1
thrName = threading.currentThread().name
print 'Starting %s' % thrName
while not done.wait(random.random() * 0.1):
msgNum += 1
msg = '%s: %d' % (thrName, msgNum)
print msg
InsertRec(msg)
finally:
done.set()
pass
class ThreadTestRun(TestCase):
def testRunIt(self):
nThisThread = 10
msgSet = set()
for x in xrange(nThisThread):
msg = 'Some message %d' % x
InsertRec(msg) # From main thread: works!
msgSet.add(msg)
self.assertEqual(MyModel.objects.count(), nThisThread)
# We use sets because .all() doesn't preserve the original order.
self.assertEqual(msgSet, set([r.message for r in MyModel.objects.all()]))
thrSet = set()
for thrNum in xrange(nThreads):
t = threading.Thread(name='Thread %d' % thrNum, target=InsertThread)
t.start()
thrSet.add(t)
done.wait(10.)
done.set()
for t in thrSet:
t.join()
Update : Here is DATABASES from settings.py: 更新 :这是来自settings.py的数据库:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': ':memory:', # os.path.join(BASE_DIR, 'db.sqlite3'),
'TEST_NAME' : ':memory:',
},
}
Update : With respect to Django's ticket #12118, I get the same symptoms using ':memory:'
or a disk file (for TEST_NAME
). 更新 :关于Django的票证#12118,我使用':memory:'
或磁盘文件(用于TEST_NAME
)得到相同的症状。
Django 1.9, Python 2.7.11. Django 1.9,Python 2.7.11。 (Same symptoms in Django 1.6.) (与Django 1.6中的症状相同。)
Change your DATABASES
like this: 像这样更改您的DATABASES
:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': ':memory:',
'TEST' :
{
'NAME': 'test_db',
}
},
}
This will force django to create a real sqlite db on the disk, instead of creating it in memory. 这将迫使django在磁盘上创建一个真正的sqlite db,而不是在内存中创建它。
Also be sure to inherit your test cases related to threading from django.test.testcases.TransactionTestCase
. 另外,还要确保从django.test.testcases.TransactionTestCase
继承与线程相关的测试用例。 If you don't do so, the threads won't see database changes made from another threads. 如果您不这样做,则这些线程将看不到其他线程对数据库所做的更改。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.