web-dev-qa-db-ja.com

Django:いくつかのモデルフィールドが互いに衝突するのはなぜですか?

ユーザーへの2つのリンクを含むオブジェクトを作成します。例えば:

class GameClaim(models.Model):
    target = models.ForeignKey(User)
    claimer = models.ForeignKey(User)
    isAccepted = models.BooleanField()

サーバーを実行しているときに次のエラーが表示されます。

  • フィールド 'target'のアクセサーは、関連フィールド 'User.gameclaim_set'と衝突します。 related_name引数を「ターゲット」の定義に追加します。

  • フィールド「claimer」のアクセサが、関連フィールド「User.gameclaim_set」と衝突します。 related_name引数を「claimer」の定義に追加します。

エラーが発生する理由とその修正方法を説明してください。

168
Oleg Tarasenko

ユーザーに対して2つの外部キーがあります。 Djangoは、通常gameclaim_setであるUserからGameClaimへの逆関係を自動的に作成します。ただし、2つのFKがあるため、2つのgameclaim_set属性があります。当然不可能です。だから、あなたはDjango逆の関係に使用する名前を伝える必要があります。

FK定義でrelated_name属性を使用します。例えば.

class GameClaim(models.Model):
    target = models.ForeignKey(User, related_name='gameclaim_targets')
    claimer = models.ForeignKey(User, related_name='gameclaim_users')
    isAccepted = models.BooleanField()
289
Daniel Roseman

Userモデルは、同じ名前の2つのフィールドを作成しようとしています。1つはGameClaimsUserであるtarget用で、もう1つはGameClaimsUserであるclaimer用です。 docs on related_name 。これは、自動生成された属性が競合しないように属性の名前を設定できるDjangoの方法です。

8
Hank Gay

OPは抽象基本クラスを使用していません...しかし、あなたがいる場合、FKのrelated_nameをハードコーディングすると(たとえば、related_name = "myname")、これらの競合エラーが多数発生することがわかります。 -基本クラスから継承されたクラスごとに1つ。以下のリンクには回避策が含まれていますが、これは簡単ですが、明らかではありません。

Django docs ...

ForeignKeyまたはManyToManyFieldでrelated_name属性を使用している場合は、常にフィールドに一意の逆の名前を指定する必要があります。通常、このクラスのフィールドは子クラスのそれぞれに含まれ、毎回属性(related_nameを含む)の値がまったく同じであるため、これは通常、抽象基本クラスで問題を引き起こします。

詳細 こちら

7

場合によっては、related_nameで追加のフォーマットを使用する必要があります-実際には、継承が使用されるときはいつでも。

class Value(models.Model):
    value = models.DecimalField(decimal_places=2, max_digits=5)
    animal = models.ForeignKey(
        Animal, related_name="%(app_label)s_%(class)s_related")

    class Meta:
        abstract = True

class Height(Value):
    pass

class Weigth(Value):
    pass

class Length(Value):
    pass

ここでは衝突はありませんが、related_nameが一度定義されると、Djangoが一意のリレーション名を作成します。

次に、Valueクラスの子では、以下にアクセスできます。

herdboard_height_related
herdboard_lenght_related
herdboard_weight_related
2

ジョーダンの答えに追加するだけです(チップジョーダンに感謝します)。アプリの上のレベルをインポートしてからアプリをインポートした場合にも発生します。

myproject/ apps/ foo_app/ bar_app/

したがって、アプリfoo_appおよびbar_appをインポートしている場合、この問題が発生する可能性があります。アプリ、foo_app、bar_appがすべてsettings.INSTALLED_APPSにリストされていました

とにかくアプリのインポートを避けたいのは、2つの異なる名前空間に同じアプリがインストールされているからです

apps.foo_appおよびfoo_app

0
lukeaus

サブモジュールをアプリケーションとしてDjangoプロジェクトに追加すると、時々次の構造が与えられると、この問題に出くわすようです:

myapp/
myapp/module/
myapp/module/models.py

次をINSTALLED_APPSに追加した場合:

'myapp',
'myapp.module',

Djangoはmyapp.mymodule models.pyファイルを2回処理し、上記のエラーをスローするようです。これは、INSTALLED_APPSリストにメインモジュールを含めないことで解決できます。

'myapp.module',

myapp.moduleの代わりにmyappを含めると、すべてのデータベーステーブルが間違った名前で作成されるため、これが正しい方法のようです。

この問題の解決策を探しているときにこの投稿に出くわしたので、ここに置いておくと思いました:)

0
Jordan Hagan