【问题标题】:Django testing and ContentType generic relatations fixturesDjango 测试和 ContentType 通用关系装置
【发布时间】:2014-04-29 01:44:41
【问题描述】:

如何在 Django 单元测试中使用 GenericRelations?

我在互联网上阅读并尝试了无数建议,但无济于事。

这个很有前途Problems with contenttypes when loading a fixture in Django

但“重置”命令在 Django 1.6 中不再存在

我的项目对 ContentType 使用 GenericForeign 键,对 auth.Users 使用外键。我使用 --natural 选项仅为我的应用程序转储了数据,但这会导致测试数据库中不存在用户的问题。现在我删除了 --natural 选项,而是转储了所有 3 个应用程序 myApp、auth、contenttypes 的数据。当我运行测试时,我得到“无法加载 contenttypes.ContentType(pk=50): columns app_label, model are not unique”。我认为这是由于导入模型时动态创建的内容类型。

使用的命令:

python manage.py dumpdata auth myApp contenttypes --natural --indent=4 > auhtmtmnatural.json

接下来我转储了 myApp,auth 离开了 contenttypes。我认为由于 ContentTypes app db 是动态创建的,并且我的灯具具有自然键,所以这应该可以工作。没有。

现在我得到了:

DeserializationError: Problem installing fixture 'auhtmtmnatural.json': ContentType matching query does not exist.

如何让带有 contetypes 的固定装置工作?在测试中使用设置和创建对象更好吗?

【问题讨论】:

    标签: django django-testing django-fixtures django-tests


    【解决方案1】:

    使用content_type: [<app_label>, <model>], 而不是content_type: <hard-coded pk of model>

    【讨论】:

      【解决方案2】:

      我意识到这个问题被问到已经一年多了,但是您(或其他人)可能想知道我能够使用固定装置来测试具有 ContentType 的通用外键的模型。不过有一个警告,那就是我必须在测试装置中硬编码 content_type_id,这可能在数据库中创建 ContentTypes 的顺序方面有点不稳定。 (由于@Lara 提到的原因,我开始用 factory_boy 重写我的测试)

      我目前使用的是 Django 1.8.3、Python 2.7.9。

      关键特性似乎是加载固定装置的顺序。在我的 tests.py 中,我有:

      tests.py:

      class MyModelViewTests(TestCase):
          fixtures = [
              'auth_user.json',
              'gfk_model.json',
              'my_model.json',
          ]
      
          def test_something(self):
              # your tests
      

      在上面,gfk_model.json 包含模型的固定装置,其中包含 ContentType 的通用外键。 my_model.json 包含您的 Django 项目或应用程序需要的任何模型的固定装置。所以我首先实例化包含通用外键的模型实例。确实,他们的 object_id 条目引用了 my_model 的数据库行,这些行还不完全存在,但一旦加载 my_model.json 固定装置就会存在。

      MyModel/models.py

      class MyModel(models.Model):
          book_title = models.TextField()
          book_isbn = models.CharField(max_length=13)
      

      GFKModel/models.py

      class GFKModel(models.Model):
          content_type = models.ForeignKey(ContentType)
          object_id = models.PositiveIntegerField()
          content_object = GenericForeignKey()
          your_field = models.TextField()
      

      如果我将通用外键与一个特定的 ContentType 相关联,那么我可以从 SQL 数据库或content_type_id = ContentType.objects.get_for_model(MyModel).pk 中获取内容类型的 ID,在 django shell (python manage.py shell) 中执行。然后我在我的装置中硬编码(yukky 我知道!)因此获得的 id(在我的情况下为 13)。

      所以,最终灯具(从转储数据中获取,然后编辑)看起来像这样

      gfk_model.json

      [
      {
          "fields": {
              "your_field": "Stuff you need to associate with my_model",
              "object_id": 1,
              "content_type": 13,
          },
          "model": "myapp.gfk_model",
          "pk": 1
      },
      {
          "fields": {
              "your_field": "Stuff you need to associate with my_model",
              "object_id": 2,
              "content_type": 13,
          },
          "model": "gfk_app.gfk_model",
          "pk": 2
      }
      ]
      

      my_model.json

      [
      {
        "pk": 1, 
        "model": "myapp.my_model", 
        "fields": {
          "book_name": "How to bath your cat", 
          "book_isbn": "123456", 
        }
      },
      {
        "pk": 2, 
        "model": "myapp.my_model", 
        "fields": {
          "book_name": "How About Wednesday?", 
          "book_isbn": "654321", 
        }
      }
      ]
      

      在 gfk_model.json 中,object_id 1 和 2 分别对应 my_model.json 的 PK 1、2。我也为 gkf_model 实例提供了 PK(尽管我可能不需要,没有尝试删除它们)。

      总而言之,让它工作起来实际上比写这篇文章要快得多!

      仅通过在测试 setUp() 中使用 ORM 来让 GFK 测试正常工作也非常简单。 factory_boy 也可以。

      如果您有几种不同的 ContentType,尤其是如果它们可能会更改它们在 contenttypes 表中的 pk,我认为固定装置不会非常成功。

      【讨论】:

        【解决方案3】:

        不应该使用固定装置的原因有几个:

        • 很慢
        • 很难更新/维护;
        • 不是练习;

        您应该使用像 factory boy 这样的“模拟”应用,而不是固定装置:

        http://factoryboy.readthedocs.org/en/latest/

        https://pypi.python.org/pypi/factory_boy/

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-07-04
          • 1970-01-01
          • 1970-01-01
          • 2011-12-24
          • 2011-02-16
          • 1970-01-01
          • 2010-12-29
          • 2020-03-18
          相关资源
          最近更新 更多