4

私はDjangoにかなり慣れていないので、今は抽象モデルの使用法を理解しようとしています。ブログサービスを作成していて、認証されたユーザーと匿名ユーザーの両方がブログの投稿にコメントできるようにしたいとします。

認証されたユーザー(特定のユーザーを参照するための外部キーを持っているだけ)にとってシナリオは非常に簡単ですが、sだけでなくsまたはsの場合Authorsはそれほど単純ではありません。UserAnonymousAuthorRegisteredAuthor

ここでの直接的なアプローチは、クラスの階層を構築することです。

class Author(models.Model):
  class Meta:
    abstract = True

class AnonymousAuthor(Author):
  name = models.CharField(max_length=128)
  def display_name(self):
    return self.name

class RegisteredAuthor(Author):
  user = models.ForeignKey(User)
  def display_name(self):
    return self.user.user_name

そして、BlogPostComment次のように定義できます。

class BlogPostComment(models.Model):
  author = models.ForeignKey(Author)
  ...

このアプローチが好きなのは、作成者が誰であっても、BlogPostCommentセットを繰り返してそれぞれを呼び出すだけで、コメントのリストを簡単に作成できるdisplay_name()からです。ここでの唯一の問題は、それが機能しないことです。Djangoのコメント:

AssertionError: ForeignKey cannot define a relation with abstract class Author

ここでの解決策は何ですか?

アップデート

私は一般的な関係がここで役立つことを知っています。しかし、それが唯一の解決策ですか?やり過ぎのように感じます。

4

1 に答える 1

6

一般的な関係は、モデルとは異なり、多くの外部キーを作成するためのソリューションです。一般に、次の場合は継承を使用します。

class Animal(models.Model):
    ...

class Dog(Animal):
    ...

そして後で:

models.ForeignKey(Animal)

aはDog-aであるため、外部キーとしても保存できます。ただし、抽象クラスの場合、これらは存在しないため、外部キーの宛先として設定することはできませ。Djangoの「抽象」モデルは、「ミックスイン」の定義に近いものです。これらは、それ自体でインスタンス化されることはなく、インスタンス化される他のクラスを構成するために使用されます。DogAnimal

したがって、ここには3つの選択肢があります。

  1. Author抽象ではなく標準モデルに変更します。次に、外部キーを作成して、好きなAuthorサブクラスに渡すことができますAuthor

  2. 一般的な外部キーを使用する

  3. そもそもモデルを分割しないでください。

ここでの最後の選択は、実際には最善の策です。なぜなら、登​​録されているか匿名であるかだけが明確な違いである場合、個別の作成者テーブルを用意する理由はないからです。これはオブジェクトの状態であり、別のタイプのオブジェクトではありません。BlueCarクラスのようなものを持つのは不適切であるのと同じように。クラスがあり、代わりにCar「青」がその属性の値です。color

あなたが別々のモデルを主張するならば。その後、プロキシモデルを使用できます。ここAnonymousAuthorで、およびRegisterAuthorは単なるエイリアスですAuthor(独自のテーブルは取得しません)が、エイリアスを使用すると、カスタマイズされたメソッドを変更または追加できます。特に、Author「匿名」またはそれぞれ「登録済み」タイプ。

于 2012-08-02T19:31:03.003 に答える