Djangoユーザーモデルを拡張して、UserProfile
モデルを作成するときに、OneToOneField(User)
とForeignKey(User, unique=True)
のどちらを使用するかについて矛盾する情報を見つけています。
これを使用する方が良いですか?:
class UserProfile(models.Model):
user = models.ForeignKey(User, unique=True)
またはこれ?:
class UserProfile(models.Model):
user = models.OneToOneField(User)
Django Doc はOneToOneField
を指定し、 Django Bookの例 はForeignKey
を使用します。
James Bennett には、矛盾する例を提供する2つのブログ投稿もあります。
前の投稿で、ベネットはForeignKey
の代わりにOneToOneField
を使用するように切り替えた理由をいくつか説明していますが、特に反対を推奨する他の投稿を見ると、私はそれを完全には理解していません。
私はあなたの好みとその理由を知りたいです。または、それも重要ですか?
この記事に記載されている唯一の本当の理由は、User
の管理ページにUser
とUserProfile
の両方のフィールドが表示されるように設定できることです。これは、少量のエルボーグリースを使用したOneToOneField
で複製できるため、管理ページに表示することに夢中になっている場合を除いて、少しわかりやすくする必要があります(「ユーザー?!ああ、いや、待って、それはユニークに設定されています。 ")私はOneToOneField
を使います。
管理ページのインラインに加えて、ForeignKey
ソリューションの他の理由は、オブジェクトが逆の関係でアクセスされるときに、正しいデフォルトのDBマネージャーを使用できることです。この例を考えてみましょう サブクラスマネージャースニペット 。例のPost
クラス定義が次のようになっているとしましょう。
_class Post(ParentModel):
title = models.CharField(max_length=50)
onetoone = models.ForeignKey(SomeModel, unique=True)
children = ChildManager()
objects = models.Manager()
_
somemodel_instance.post_set.all()[0]
を呼び出すことにより、最初の(デフォルトの)マネージャーをPost
として定義することで示されるように、ChildManager
クラスの目的のサブクラスオブジェクトを取得します。一方、OneToOneField
では、_somemodel_instance.post
_を呼び出すことにより、Post
クラスインスタンスを取得します。いつでも_somemodel_instance.post.subclass_object
_を呼び出して同じ結果を得ることができますが、デフォルトのマネージャーは他の種類のトリックを実行でき、FK
ソリューションはそれらをうまく隠します。
カスタムマネージャーコードを所有していて変更できる場合は、正当な1to1フィールドの代わりにFKを使用する代わりに、 _use_for_related_fields
_ 属性を使用できますが、それでも、不明な点があるために失敗する可能性があります。自動管理者の迷惑です。私が覚えている限り、上記の例では失敗します。
逆関係に関連するOneToOneField
を一般的に使用しないその他の理由:OneToOneField
を介して定義された逆関係を使用すると、Manager
逆関係のForeignKey
とは対照的に、モデルインスタンスが取得され、その結果、常にDBヒットが発生します。これは、(_meta.get_all_related_objects()
を介して)逆の関係でいくつかの一般的なことを行い、それらをすべて使用するかどうかわからない場合はコストがかかります。