django 1.8 测试模型和迁移

Posted

技术标签:

【中文标题】django 1.8 测试模型和迁移【英文标题】:django 1.8 tests with models and migrations 【发布时间】:2015-06-28 15:14:29 【问题描述】:

我使用 django 1.8 我有一个参考 django.contrib.contenttypes.ContentType 的模型:

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:

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)

当我尝试在没有迁移的情况下创建数据库(以及“测试”)时,我收到一个无效引用错误:

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

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

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

在我尝试测试我的应用后,我收到一个错误,引用 myob_testobj 不存在:

./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”

/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

如何对模型使用测试? 谢谢。

【问题讨论】:

【参考方案1】:

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

之后运行python manage.py makemigrations myobj,然后将创建TestObj 的迁移。这样您就可以运行测试了。

【讨论】:

【参考方案2】:

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

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

您看到此错误的原因是,当您运行 syncdb 时,它没有运行 ContentTypes 迁移,因此数据库中不存在这些模型。运行单元测试时,Django 会自动执行 migrate 命令,这可以解释为什么它在单元测试中有效,但在开发服务器上手动运行时无效。

【讨论】:

syncdb 没那么重要。有/没有迁移文件的测试问题。如果该文件存在 - 没有创建带有测试模型的表,如果不存在 - 我收到一个错误,没有引用 django_content_type。迁移而不是 syncdb 命令不能解决我的问题。谢谢你的回答

以上是关于django 1.8 测试模型和迁移的主要内容,如果未能解决你的问题,请参考以下文章

将旧 (Django 0.97) 模型数据导入/迁移到 Django 1.8 或更高版本

在 django 1.8 中将数据从原始用户模型迁移到自定义用户模型

Django 1.8:删除/重命名数据迁移中的模型字段

Django 1.8 迁移:有啥方法可以从不再有模型的数据库表中获取数据?

Django 1.8:删除迁移文件夹后未检测到迁移

postgres 的 Django 1.8 迁移错误