web-dev-qa-db-ja.com

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

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

100
user27478

manage.py dumpdata --naturalは、外部キーのより永続的な表現を使用します。 In Djangoそれらは「自然キー」と呼ばれます。例えば:

  • Permission.codenamePermission.idの代わりに使用されます
  • User.usernameUser.idの代わりに使用されます

詳細: 「Djangoオブジェクト)のシリアル化」の自然キーセクション

dumpdataのその他の便利な引数:

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

はい、これは本当に刺激的です。しばらくの間、フィクスチャをロードする前にcontenttypesアプリで「manage.py reset」を実行することで回避しました(ダンプされたバージョンとは異なる自動生成されたcontenttypesデータを削除するため)。それはうまくいきましたが、最終的には、面倒なフィクスチャーと放棄されたフィクスチャにうんざりして、まっすぐなSQLダンプが好まれました(もちろん、DBの移植性は失われます)。

更新-最良の答えは--naturalフラグをdumpdataに追加します(以下の回答に記載されています)。このフラグを書いたとき、そのフラグはまだ存在していませんでした。

33
Carl Meyer

フィクスチャを作成するときにコンテンツタイプをスキップしてみてください。

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

単体テストでも同様の状況で機能し、コンテンツタイプに関するあなたの洞察は本当に役に立ちました!

30
Evgeny

ここでの答えはすべて古いです... 2017年の時点で、最良の答えは次のとおりです。

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

私はMySQLを使用していませんでしたが、代わりにライブサーバーからsqliteにいくつかのデータをインポートしました。 contenttypesを実行する前にloaddataアプリデータをクリアすると、トリックが実行されました。

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

その後

python manage.py loaddata data.json
11
MadeOfAir

ダンプファイルを読み込む前に、単体テストからcontenttypesアプリをリセットすることにより、テストケースでこの問題を解決しました。 Carlはすでに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を防ぎます。

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

これは私のために動作します。ここでは、実際のモデルのすべてを除外しています。

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

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

Django 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 documentation によると、--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
3
lmiguelvargasf
./manage.py dumpdata app.Model --natural-foreign

変更されます

  "content_type": 123

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

フィクスチャはTestCaseで動作します

2
Daniil Mashkin

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

多対多のリレーションシップテーブルがあります。主キーと、他のテーブルへの2つの外部キーがあります。 2つの外部キーがdifferent pkを使用してテーブルにすでにある別のエントリと同じであるフィクスチャにエントリがある場合、失敗することがわかりました。 M2Mのリレーションシップテーブルには、2つの外部キーに対して「一緒にユニーク」があります。

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

1
orblivion

私は時々前に同様のエラーに遭遇しました。必要なテーブルを作成する前にフィクスチャをロードしようとしていたことが判明しました。だから私はやった:

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

そしてそれは魅力のように働いた

1
James Wanderi

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

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

私に最適なのは、単にtruncate table Django_content_type; syncdbとTHENがデータをロードした後。

もちろん、initial_data.jsonのオートロードではフォールボールになります。

1
h3.