Тестирование Django и значение contentType универсальных приспособлений relatations


Как я использую GenericRelations в модульном тестировании Django?

Я прочитал и попробовал бесчисленные предложения в интернете, но безрезультатно.

Этот был многообещающим Проблемы с contenttypes при загрузке фикстура в Django

Но команда "сброс" больше не существует в Django 1.6

Мой проект использует ключ GenericForeign в contentType и внешним ключом для аутентификации.Пользователи. Я сбросил данные только для моего приложения, используя опцию -- natural, но это привело к проблема, когда пользователи не существовали в тестовой базе данных. Теперь я удалил --естественный параметр, а вместо этого сбросил данные для всех 3 приложение приложений, авт, contenttypes. Когда я запускаю тест, я получаю "не удалось загрузить contenttypes.Значение contentType(ПК=50): app_label колонки, модель не уникальна". Я думаю, это связано с тем, что типы контента создаются динамически при импорте моделей.

Используемая команда:

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.

Как заставить fixutres с contetypes работать? Лучше использовать настройки и создать объекты в тестировании?

3 3

3 ответа:

Существует несколько причин, по которым вы не должны использовать светильники:

  • это медленно
  • это трудно обновить / поддерживать;
  • не является практикой;

Вместо светильников вы должны использовать "макет" приложения, как factory boy:

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

Https://pypi.python.org/pypi/factory_boy/

Используйте content_type: [<app_label>, <model>], вместо content_type: <hard-coded pk of model>

Я понимаю, что прошло уже больше года с тех пор, как был задан этот вопрос, однако вам (или кому-то еще) может быть интересно узнать, что я смог использовать fixtures при тестировании модели с универсальным внешним ключом ContentType. Однако есть одно предостережение, которое заключается в том, что мне пришлось жестко кодировать content_type_id в тестовых установках, и это, вероятно, немного неустойчиво с точки зрения порядка, в котором ContentTypes создаются в базе данных. (Я начинаю переписывать свои тесты с factory_boy по причинам @Lara упоминалось)

В настоящее время я использую 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. Моя модель.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()

Если я связываю универсальный внешний ключ с одним конкретным типом контента, то я могу получить идентификатор типа контента из базы данных SQL или content_type_id = ContentType.objects.get_for_model(MyModel).pk, выполненный в оболочке django (python manage.py shell). Я тогда жестко закодировал (Юкки я знаю!) идентификатор таким образом получается (13 в моем случае) в моих приспособлениях.

Итак, наконец, светильники (полученные из dumpdata, а затем отредактированные) выглядят примерно так

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 в объект 1 и 2 соответствуют ПКС 1, 2 в my_model.json соответственно. Я также предоставил PKs для экземпляров gkf_model (хотя, возможно, мне это не нужно, я не пытался удалить их).

В общем, это на самом деле было гораздо быстрее заставить его работать, чем написать этот пост!

Также довольно просто заставить тесты GFK работать, просто используя ORM в тестовой установке (). Также прекрасно и с factory_boy.

Если у вас есть несколько различных типов контента, и особенно если они, вероятно, изменят свой pk в таблице contenttypes, я не думаю, что светильники будут очень успешными.