Django / sqlite3 "OperationalError: no such table" for threaded operations

For all the questions I read in the docs, both Django and py-sqlite3 should be fine with streaming access. (Right?) But this piece of code is not suitable for me. The work in the main thread works, but not in the threads that I create. There I get:

File "C: \ python27 \ Lib \ site-packages \ Django-1.9-py2.7.egg \ Django \ db \ engines \ sq.m lite3 \ base.py", line 323, executed by return Database.Cursor .execute (self, query, params)

OperationalError: no such table : thrtest_mymodel

What is the problem?

How can I track what is happening with the Django patch or something that is needed to fix it? Django's point of failure is quite discouraging. I can’t say how to look at which tables he sees, or what differences to look for between the 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 DATABASE DATA: settings.py:

 DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': ':memory:', # os.path.join(BASE_DIR, 'db.sqlite3'), 'TEST_NAME' : ':memory:', }, } 

Update. As for Django ticket # 12118, I get the same symptoms using ':memory:' or a file on disk (for TEST_NAME ).

Django 1.9, Python 2.7.11. (The same symptoms are in Django 1.6.)

+5
source share
1 answer

Modify the DATABASES as follows:

 DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': ':memory:', 'TEST' : { 'NAME': 'test_db', } }, } 

This will force django to create a real sqlite db on disk, rather than creating it in memory.

Also, be sure to inherit your streaming test cases from django.test.testcases.TransactionTestCase . If you do not, the threads will not see database changes made from other threads.

+3
source

Source: https://habr.com/ru/post/1240097/


All Articles