django 1.8测试模型和迁移

django 1.8 tests with models and migrations

我用django 1.8我有一个引用django.contrib.contenttypes.contenttype的模型:

1
2
3
4
5
6
7
8
9
10
11
12
13
from django.db import models
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType


class TaggedItem(models.Model):
    tag = models.SlugField()
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    content_object = GenericForeignKey('content_type', 'object_id')

    def __str__(self):              # __unicode__ on Python 2
        return self.tag

我有一个tests.py:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class TestObj(models.Model):
    value = models.IntegerField(default=42, null=False)

    def __str__(self):
        text ="%s-%i" % ("name", self.value)
        return text


class MyUnitTest(TestCase):
    def setUp(self):
        TestObj.objects.create(value=40)
        TestObj.objects.create()

    def test_my_test(self):
        obj1 = TestObj.objects.get(value=40)
        obj2 = TestObj.objects.get(value=42)
        self.assertEqual(obj1.value, 40)
        self.assertEqual(obj2.value, 42)

当我尝试在不进行迁移的情况下创建数据库时(以及"test"),我会得到一个带有无效引用的错误:

1
2
3
./manage.py syncdb
...
django.db.utils.ProgrammingError: ERROR: reference"django_content_type" does not exist

但是,如果我创建一个迁移(/manage.py makemigrations myobj),则迁移只包含models.py模型(taggedItem):

1
2
3
Migrations for 'myobj':
  0001_initial.py:
    - Create model TaggedItem

在我尝试测试我的应用程序后,发现参考myob_testobj不存在错误:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
./manage.py test -v3
Creating test database for alias 'default' ('testdb_49308_4288843')...
Operations to perform:
  Synchronize unmigrated apps: staticfiles
  Apply all migrations: myobj, contenttypes, sessions
Synchronizing apps without migrations:
Running pre-migrate handlers for application contenttypes
Running pre-migrate handlers for application sessions
Running pre-migrate handlers for application myobj
  Creating tables...
    Running deferred SQL...
  Installing custom SQL...
Loading 'initial_data' fixtures...
Checking 'mypro' for fixtures...
No fixture 'initial_data' in 'mypro'.
Installed 0 object(s) from 0 fixture(s)
Running migrations:
  Rendering model states... DONE (0.010s)
  Applying contenttypes.0001_initial... OK (0.133s)
  Applying contenttypes.0002_remove_content_type_name... OK (0.017s)
  Applying myobj.0001_initial... OK (0.217s)
  Applying sessions.0001_initial... OK (0.233s)
Running post-migrate handlers for application contenttypes
Adding content type 'contenttypes | contenttype'
Running post-migrate handlers for application sessions
Adding content type 'sessions | session'
Running post-migrate handlers for application myobj
Adding content type 'myobj | taggeditem'
Adding content type 'myobj | testobj'
Traceback
...
django.db.utils.ProgrammingError: ERROR: reference"myobj_testobj" does not exist

如果不使用迁移和运行测试,则会创建表myobj_testobj,但会得到一个没有引用"django_content_type"的错误。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/manage.py test -v3
Creating test database for alias 'default' ('testdb_773982_6463361')...
Operations to perform:
  Synchronize unmigrated apps: staticfiles, myobj
  Apply all migrations: contenttypes, sessions
Synchronizing apps without migrations:
Running pre-migrate handlers for application contenttypes
Running pre-migrate handlers for application sessions
Running pre-migrate handlers for application myobj
  Creating tables...
    Creating table myobj_taggeditem
    **Creating table myobj_testobj**
    Running deferred SQL...
Traceback
...
django.db.utils.ProgrammingError: ERROR: reference"django_content_type" does not exist

如何在模型中使用测试?谢谢您。


Django无法发现型号TestObj,因为您的test.py不是应用程序,并且没有任何已安装的应用程序描述settings.INSTALLED_APPS中的TestObj。您需要将模型TestObj添加到模块myobj.models中。

之后运行python manage.py makemigrations myobj,然后创建testobj的迁移。所以你可以运行你的测试。


您需要在Django 1.7或更高版本上使用迁移。syncdb已被弃用,不应再使用。

相反,您应该使用makemigrations,然后使用migrate。

您看到此错误的原因是,当您运行syncdb时,它不会运行contenttypes迁移,因此数据库中不存在这些模型。当运行单元测试时,django会自动执行migrate命令,这将解释为什么它在单元测试中工作,但在dev服务器上手动运行时不工作。