2016-01-07 31 views
5

Wszystko, co czytałem w dokumentach, zarówno Django, jak i py-sqlite3 powinno być w porządku z dostępem z gwintem. (Tak?) Ale ten fragment kodu zawodzi dla mnie. Operacje w wątku głównym działają, ale nie w wątkach, które utworzę. Dostaję:Django/sqlite3 "OperationalError: no such table" na operacji gwintowania

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

Na czym polega problem?

W jaki sposób mogę znaleźć dokładnie to, co dzieje się z łataniem Django lub cokolwiek jest konieczne, aby to naprawić? Punkt porażki w Django jest dość zastraszający. Nie mogę powiedzieć, jak wyświetlić tabele, które widzą, ani jakie różnice szukać między wątkami głównymi i innymi.

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

Aktualizacja: Oto baz danych z settings.py:

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

aktualizacji: W odniesieniu do Django numerem # 12118, mam te same objawy wykorzystujące ':memory:' lub pliku na dysku (dla TEST_NAME).

Django 1.9, Python 2.7.11. (te same objawy w Django 1.6.)

+0

Jak wyglądają twoje ustawienia DATABASES? –

+0

Wydaje się to powiązane, chociaż wydaje się być poprawione w wersjach 1.8.x i 1.9.x. https://code.djangoproject.com/ticket/12118 – Krab

Odpowiedz

3

zmienić DATABASES tak:

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

To zmusi Django stworzyć prawdziwe sqlite db na dysku, zamiast tworzenia go w pamięci.

Pamiętaj również, aby dziedziczyć przypadki testowe związane z gwintowaniem od django.test.testcases.TransactionTestCase. Jeśli tego nie zrobisz, wątki nie będą wyświetlać zmian w bazie danych dokonanych z innych wątków.

+0

Dzięki za odpowiedź. Ale jest to jedna z konfiguracji, które wypróbowałem (ostatnia aktualizacja powyżej - starsza wersja django używa "TEST_NAME" a "TEST": {'NAME': ...}). Testy, które po prostu sprawdzają i kończą całą pracę, ale mój test wielowątkowy, który działa dość długo, nagle pośrodku, informuje, że baza danych się zmieniła, a wszystkie tabele zniknęły. Podobnie jak baza danych automatycznie wycofana. – JimB

+0

Dziwne:/jako ostatnią opcję możesz powiedzieć django, aby zachować bazę danych po teście za pomocą klawisza '--keepdb'. – eviltnan

+0

Zapisałeś mój dzień –