2016-01-07 22 views
5

Djangoとpy-sqlite3の両方がスレッドアクセスでうまくいくはずです。 (右?)しかし、このコードスニペットは私のために失敗します。メインスレッドでの操作は機能しますが、作成したスレッドでは機能しません。そこに私は得る:Django/sqlite3 "OperationalError:そのようなテーブルはありません"

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)

OperationalError: no such table: thrtest_mymodel

何が問題なのですか?

Djangoを修正するために何が起こっているのか、それを修正するために必要なことを正確に追跡するにはどうすればよいですか? Djangoの失敗のポイントは非常に控え目です。どのテーブルを参照するか、またはメインスレッドと他のスレッドの間でどのような相違点があるかを見分ける方法はわかりません。

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() 

更新

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

更新:ここではsettings.pyのデータベースがあるDjangoのチケット#12118に関しては、私は(':memory:'を使用して、同じ症状やディスクファイルを取得TEST_NAME)。

Django 1.9、Python 2.7.11。 (ジャンゴ1.6で同じ症状。)

+0

DATABASESの設定はどのようになっていますか? –

+0

これは1.8.xと1.9.xで修正されているようですが、これは関連しているようです。 https://code.djangoproject.com/ticket/12118 – Krab

答えて

3
は変更

あなたのこのようなDATABASES

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

これは代わりに、メモリに作成するのではなく、ディスク上の実際のsqliteのDBを作成するためのDjangoを強制します。

スレッディングに関するテストケースを継承することも、django.test.testcases.TransactionTestCaseから行ってください。そうしないと、スレッドは別のスレッドからのデータベース変更を見ません。

+0

答えをありがとう。しかし、これは私が試した設定の一つです(上記の最後のアップデート - 古いdjangoのバージョンは 'TEST_NAME'対 'TEST':{'NAME':...})。何かをチェックして正常に動作することをテストしますが、途中で突然実行されるマルチスレッドテストでは、データベースが変更され、すべてのテーブルがなくなったことを通知します。データベースと同様に自動的にロールバックされます。 – JimB

+0

strange:/最後のオプションとして、 '--keepdb'キーを使ってテスト後にデータベースを保持するdjangoと言うことができます。 – eviltnan

+0

あなたは私の日を保存しました –

関連する問題