Djangoでフィクスチャをロードする際のコンテンツタイプに関する問題


104

contenttypesの競合が原因で、MySQLデータベースにDjangoフィクスチャをロードできません。まず、次のように自分のアプリからのみデータをダンプしてみました。

./manage.py dumpdata escola > fixture.json

しかし、私のアプリ「escola」は他のアプリケーションのテーブルを使用しているため、外部キーの問題が何度も見つかりません。これに到達するまで、私は追加のアプリを追加し続けました:

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

データをテストフィクスチャとしてロードしようとすると、問題は次の制約違反になります。

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

問題は、Djangoがフィクスチャの主キー値と競合する異なる主キー値を持つコンテンツタイプを動的に再作成しようとしていることです。これは、ここに記載されているバグと同じように見えます: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

続きを読む:「djangoオブジェクトのシリアル化」の自然キーセクション

他のいくつかの有用な引数dumpdata

  • --indent=4 人間が読めるようにします。
  • -e sessions セッションデータを除外する
  • -e admin 管理サイトでの管理アクションの履歴を除外する
  • -e contenttypes -e auth.Permission中に毎回スキーマから自動的に再作成されるオブジェクトを除外しますsyncdb。一緒にのみ使用して--naturalください。そうしないと、ID番号が正しく整列しなくなる可能性があります。

1
@skyjurなぜ常に使用-e contenttypes -e auth.permissionするの--naturalですか?私は--naturalオプションなしで試したところ、うまくいきました。また、ここドキュメントでは、DUMPING auth.permissionおよびの場合、このオプションを使用する必要があると述べていますcontenttypes
wlnirvana 14

6
@winirvanaは、ゼロから開始してsyncdbを実行した後、新しく作成されContentTypePermission以前と同じIDを取得することが保証されないためです。データダンプには、データをロードする別のデータベース上の異なるオブジェクトを参照する可能性のあるIDが含まれています。これらの理由のいずれかが原因で機能した可能性があります:1)データにこれらのオブジェクトへの参照がなかった2)Permission / ContentTypesの元のIDが保持された3)loaddataは成功したが、実際にはオブジェクトが原因で破損したデータがある間違ったオブジェクトを参照していて、まだそれについて知らない
2015

12
Flag --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代わりに使用します。
Code-Apprentice

35

はい、これは本当にイライラします。しばらくの間、フィクスチャをロードする前にcontenttypesアプリで「manage.pyリセット」を実行して回避しました(ダンプされたバージョンとは異なる自動生成されたcontenttypesデータを取り除くため)。それはうまくいきましたが、結局私はストレートSQLダンプを支持するために手間とフィクスチャを放棄することにうんざりしました(もちろん、あなたはDBの移植性を失います)。

更新 -最良の答えは、以下の答えに記載されているように、--naturalフラグをに使用dumpdataすることです。私がこの答えを書いたとき、その旗はまだ存在していませんでした。


3
私もこれに遭遇しました、contenttypesアプリをリセットすることも私にとってはうまくいきました。先端をありがとう!
ボー

どのようにリセットしましたか?テストケースクラスでは?例を挙げてください
Oleg Tarasenko

4
私は単体テストにフィクスチャを使用していません。テストとの同期を維持する方が簡単であるため、通常、setup()メソッドでORMを使用してテストデータを作成します。そのため、TestCaseクラスでこれを行う必要はありませんでしたが、DjangoのTestCaseクラスのコードをざっと見れば、syncdbの後、サブクラスでフィクスチャをロードする前に、リセットを実行する方法を理解できるはずです。私にとっては、「./ manage.py loaddata my_fixture」の前のbashスクリプトの「./manage.py reset contenttypes」だけでした。
カールマイヤー

32

フィクスチャを作成するときにcontenttypesをスキップしてみてください:

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

これでうまくいきます。ここでは、実際のモデルに関するすべてを除外しています。

  • 作成したモデル以外のモデルが表示された場合は、それらを安全に除外できます。このアプローチの欠点の1つは、認証データだけでなくログデータも失うことです。

6

外部キーと多対多の関係を表すには、自然キーを使用する必要があります。さらに、アプリ内のテーブルとアプリ内のsessionテーブルを除外することをお勧めします。sessionslogentryadmin

Django 1.7以降

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

Django <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

Django 2.2.5

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

それは私を助けました


loaddata時に問題が発生します。新しいデータベースのcontenttypeと一致しない可能性があります
yang zhou

1

私が考え出した別の可能な答えを与えます。多分それはOPを助けるでしょう、多分それは他の誰かを助けるでしょう。

多対多の関係テーブルがあります。主キーと、他のテーブルへの2つの外部キーがあります。2つの外部キーがテーブルに既に存在する別の pkを持つ別のエントリと同じであるフィクスチャにエントリがある場合、失敗することがわかりました。M2Mリレーションシップテーブルには、2つの外部キーの「一意の組み合わせ」があります。

したがって、M2M関係が壊れている場合は、追加している外部キーを確認し、データベースを調べて、そのFKのペアがすでに別のPKの下にリストされているかどうかを確認します。


1

それは本当に、本当に迷惑です..私は毎回これに噛まれます。

--exclude contenttypesおよび--naturalを使用してデータをダンプしようとしましたが、常に問題が発生します。

私にとって最も効果的なのはtruncate table django_content_type;、syncdbを実行してからデータをロードすることです。

もちろん、initial_data.jsonのオートローディングではフォールボールです。


私にとって、loaddataの前にテーブルを切り捨てると、さまざまなエラーが発生します。この手法では運がありません。
シャッカー

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

私は上からすべての方法を試しましたが、何もうまくいきませんでした。完全な認証モデルを除外する必要があり、正常に動作します。

python manage.py dumpdata --natural-primary --exclude=contenttypes --exclude=auth --exclude=admin.logentry --exclude=sessions.session --indent 4 > live.json
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.