Проблеми з типами контенту при завантаженні кріплення в Django


104

У мене виникають проблеми із завантаженням світильників Django в мою базу даних MySQL через конфлікти типів вмісту. Спочатку я спробував скинути дані лише з мого додатка, наприклад:

./manage.py dumpdata escola > fixture.json

але мені не вистачало проблем із зовнішніми ключовими словами, оскільки в моєму додатку "ескола" використовуються таблиці інших програм. Я продовжував додавати додаткові додатки, поки не дійшов до цього:

./manage.py dumpdata contenttypes auth escola > fixture.json

Тепер проблема полягає в наступному порушенні обмежень, коли я намагаюся завантажити дані в якості тестового кріплення:

IntegrityError: (1062, "Duplicate entry 'escola-t23aluno' for key 2")

Здається, проблема полягає в тому, що Джанго намагається динамічно відтворити типи контенту з різними значеннями первинного ключа, що суперечать значенню первинного ключа з кріплення. Схоже, помилка задокументована тут: http://code.djangoproject.com/ticket/7052

Проблема полягає в тому, що рекомендованим рішенням є скидання програми contenttypes, що я вже роблю !? Що дає? Якщо це має значення, у мене є деякі дозволи на власну модель, як це задокументовано: http://docs.djangoproject.com/en/dev/ref/models/options/#permissions

Відповіді:


148

manage.py dumpdata --naturalбуде використовувати більш міцне представлення іноземних ключів. У джанго їх називають "природними ключами". Наприклад:

  • Permission.codename використовується на користь Permission.id
  • User.username використовується на користь User.id

Детальніше: розділ природних ключів у "серіалізації об'єктів джанго"

Деякі інші корисні аргументи для dumpdata:

  • --indent=4 зробити його читабельним для людини.
  • -e sessions виключити дані сеансу
  • -e admin виключити історію дій адміністратора на сайті адміністратора
  • -e contenttypes -e auth.Permissionвиключати об'єкти, які автоматично відтворюються зі схеми щоразу протягом syncdb. Використовуйте його лише разом з --naturalіншим випадком, якщо у вас можуть бути неправильно вирівняні ідентифікаційні номери.

1
@skyjur Чому завжди використовувати -e contenttypes -e auth.permissionз --natural? Я просто спробував без --naturalваріанту, і це спрацювало. Також тут представлена документація говорить, що слід використовувати цю опцію, якщо DUMPING auth.permission і contenttypes.
wlnirvana

6
@winirvana тому, що після запуску з нуля і синхронізації, новостворений ContentTypeі Permissionне гарантовано отримає той самий ідентифікатор, як раніше. Ваш дамп даних містить ідентифікатори, які можуть посилатись на різні об'єкти в анафірній базі даних, куди ви будете завантажувати дані. Це могло працювати для вас через одну з таких причин: 1) ваші дані не мали посилання на ці об’єкти 2) оригінальні ідентифікатори дозволу / ContentTypes збереглися 3) ваші дані завантаження були успішними, але у вас фактично є пошкоджені дані через об’єкти посилаючись на неправильні об’єкти, а ви про це ще не знаєте
Ski Ski

12
--naturalЗараз прапор застарілий на користь --natural-foreign--natural-primary)
frnhr

16
Заключною командою може бути:manage.py dumpdata --natural-foreign --natural-primary -e contenttypes -e auth.Permission --indent 4 > project_dump.json
Паоло

4
--naturalтепер було повністю вилучено, а не просто застаріле. Використовуйте --natural-foreignабо --natural-primaryзамість цього.
Код-учень

35

Так, це дійсно дратує. Деякий час я працював над цим, роблячи "скидання.py скидання" на додаток contenttypes перед завантаженням кріплення (щоб позбутися від автоматично створених даних типів контенту, які відрізнялися від демпінгової версії). Це спрацювало, але врешті-решт я захворів на клопоти та покинуті кріплення повністю на користь прямих скидів SQL (звичайно, тоді ви втрачаєте портативність БД).

оновлення - найкраща відповідь - використовувати --naturalпрапор dumpdata, як зазначено у відповіді нижче. Та прапор ще не існував, коли я писав цю відповідь.


3
Я також стикався з цим, скидаючи додаток типу вмісту, працював і на мене. Дякую за пораду!
Beau

Як ви їх скинули? У класі тестових випадків? Наведіть мені приклад, будь ласка
Олег Тарасенко

4
Я не використовую світильники для unittests, я, як правило, створюю тестові дані за допомогою ORM методом setup (), оскільки простіше підтримувати синхронізацію з тестами. Тож мені ніколи не доводилося робити цього в класі TestCase, хоча я впевнений, що якщо ти заглянеш у код для класу TestCase Джанго, ти зможеш зрозуміти, як зробити скидання після синхронізації після синхронізації та перед завантаженням підкласу в підклас. Для мене це було просто "./manage.py скинути типи контенту" в скрипті bash до "./manage.py loaddata my_fixture".
Карл Мейєр

32

Спробуйте пропустити типи вмісту, створюючи кріплення:

./manage.py dumpdata --exclude contenttypes > fixture.json

Це працювало для мене в подібній ситуації для одиничних тестів, ваше розуміння щодо типів контенту справді допомогло!


31

Відповіді тут усі старі ... Найкраща відповідь станом на 2017 рік:

manage.py dumpdata --natural-foreign --natural-primary -e contenttypes -e auth.Permission --indent 4

11

Я не використовував MySQL, але натомість імпортував деякі дані з живого сервера в sqlite. Очищення contenttypesданих додатка перед виконанням loaddataвиконало хитрощі:

from django.contrib.contenttypes.models import ContentType
ContentType.objects.all().delete()
quit()

І потім

python manage.py loaddata data.json

django.core.exceptions.ImproperlyConfigured: Запрошене налаштування INSTALLED_APPS, але налаштування не налаштовано. Перш ніж отримати доступ до налаштувань, потрібно або визначити змінну середовища DJANGO_SETTINGS_MODULE, або виклик settings.configure ().
Барні

Це, мабуть, найкраще працює в ручці користувацької команди управління.
Барні

10

Цю проблему я вирішив у своїх тестових випадках, скинувши додаток contenttypes з одиничного тесту до завантаження мого файлу. Карл запропонував це вже використовуючи manage.pyкоманду, і те саме я роблю лише call_commandметодом:

>>> from django.core import management
>>> management.call_command("flush", verbosity=0, interactive=False)
>>> management.call_command("reset", "contenttypes", verbosity=0, interactive=False)
>>> management.call_command("loaddata", "full_test_data.json", verbosity=0)

Мій full_test_data.jsonпристрій містить дамп програми contenttypes, який відповідає решті даних тесту. Скинувши додаток перед завантаженням, це запобігає повторенню ключа IntegrityError.


7
python manage.py dumpdata --natural-primary --exclude=contenttypes --exclude=auth.Permission --exclude=admin.logentry --exclude=sessions.session --indent 4 > initial_data.json

Це працює для мене. Тут я виключаю все, що відповідає фактичним моделям.

  • Якщо ви бачите будь-яку іншу модель, окрім створених вами моделей, їх можна сміливо виключати. Одним з недоліків такого підходу є втрата даних журналу, а також аутентичних даних.

6

Потрібно використовувати природні ключі, щоб представити будь-який зовнішній ключ та багатозахисні стосунки. Крім того, може бути непоганою ідея виключити sessionтаблицю в sessionsдодатку та logentryтаблицю в adminдодатку.

Джанго 1.7+

python manage.py dumpdata --natural-foreign --exclude contenttypes --exclude auth.permission --exclude admin.logentry --exclude sessions.session --indent 4 > fixture.json

Джанго <1,7

python manage.py dumpdata --natural --exclude contenttypes --exclude auth.permission --exclude admin.logentry --exclude sessions.session --indent 4 > fixture.json

Відповідно до документації Django , --naturalу версії 1.7 застаріла, тому --natural-foreignзамість цього слід використовувати варіант .

Ви також можете опустити первинний ключ у серіалізованих даних цього об'єкта, оскільки він може бути обчислений під час десеріалізації шляхом передачі --natural-primaryпрапора.

python manage.py dumpdata --natural-foreign --natural-primary --exclude contenttypes --exclude auth.permission --exclude admin.logentry --exclude sessions.session --indent 4 > fixture.json

2
./manage.py dumpdata app.Model --natural-foreign

зміниться

  "content_type": 123

до

  "content_type": [
    "app_label",
    "model"
  ],

І кріплення працює TestCaseнаразі


2

Джанго 2.2.5

python manage.py dumpdata --exclude=contenttypes > datadump.json

це мені допомогло


Це спричинить проблему, коли завантаження даних, можливо, невідповідність контенту контенту в новій базі даних
yang zhou

1

Я збираюся дати ще одну можливу відповідь, яку я щойно зрозумів. Можливо, це допоможе ОП, можливо, допоможе комусь іншому.

У мене є таблиця стосунків багато-багато. Він має первинний ключ та два зовнішні ключі до інших таблиць. Я виявив, що якщо у мене є запис у світильнику, два зовнішні ключі якого є таким же, як інший запис у таблиці з іншим pk, він вийде з ладу. У таблицях відносин M2M є "унікальне разом" для двох закордонних ключів.

Отже, якщо це стосунок M2M, який порушується, погляньте на додані зовнішні ключі, погляньте на свою базу даних, щоб побачити, чи є ця пара FKs вже переліченими під іншим ПК.


1

Це насправді, насправді дратує .. Мене це кожного разу кусає.

Я намагався демпдатувати з - виключати типи контенту та --природні, у мене завжди виникають проблеми.

Що найкраще для мене - це просто зробити truncate table django_content_type;після синхронізації та ТОГО завантаження даних.

Звичайно, для автоматичного завантаження Initial_data.json ви перебуваєте в базі.


Для мене обрізка таблиці перед завантаженням даних просто викликає різні помилки. Не щастить цій техніці.
шейкер

1

Іноді я стикався з подібною помилкою. Виявилося, що я намагався завантажити світильники перед створенням необхідних таблиць. Так я і зробив:

$ python manage.py makemigrations
$ python manage.py migrate
$ python manage.py loaddata fixtures/initial_data.json

І це спрацювало як шарм


0

У моєму випадку я вивантажив дані з auth( ./manage.py dumpddata auth > fixtures/auth.json), щоб використовувати кріплення для тестування.

Розвиток тривав, і я зняв більшість моделей, які я визначив, models.pyі саме тоді я почав бачити цю набридливу проблему.

Моє рішення знову регенерувало кріплення auth.json. Цей видалив багато записів, auth.permissionпов'язаних зі старими моделями, які я мав.


0

Я спробував кожен метод зверху, нічого не працювало для мене. Я маю виключити повну модель auth і працює чудово.

python manage.py dumpdata --natural-primary --exclude=contenttypes --exclude=auth --exclude=admin.logentry --exclude=sessions.session --indent 4 > live.json
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.