誰かがこれを書いたmodels.py
documents = generic.GenericRelation(Document)
ForeignKey
やOneToMany
フィールドのような他のタイプとどう違うのか知りたいです。
これに関する十分なドキュメントを見たことがない
ここで何かを見つけたら
しかし、最初から contenttype が何をするのか、そしてなぜそれを使うのか理解していません。
データベースにさまざまなオブジェクト (画像、ビデオ、曲など) があり、それぞれにキーワードを追加したいとします。ただし、キーワードを持つすべてのオブジェクトのすべてのキーワードを管理する単一のキーワード テーブルが必要です。したがって、モデルは次のようになります。
class Image(models.Model):
# ...
class Video(models.Model):
# ...
class Keyword(models.Model):
keyword = models.CharField(max_length=64)
モデルができたら、どうにかしてキーワードを他のオブジェクトに関連付ける必要があります。そのためには、多対多の関係を使用する必要があります。
class KeywordItem(models.Model):
keyword = models.ForeignKey('Keyword')
image = models.ForeignKey('Image')
ただし、これは画像のキーワードのみを追加できるため機能しませんが、ビデオなどのキーワードも必要です。つまり、このアプローチの問題は、キーワードを特定のテーブルにリンクすることを制限することです。画像テーブル。したがって、アイデアはそれを行うのではなく、任意のテーブルにリンクしてから、リンクするテーブルを指定するだけです:
class KeywordItem(models.Model):
keyword = models.ForeignKey('Keyword')
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
object = generic.GenericForeignKey('content_type', 'object_id')
はリンク先のcontent_type
テーブルを指定し、 はリンクobject_id
先のテーブルの行の主キーを指定します。
問題は、リンクしているテーブルをどのように指定するかです。1 つの解決策は、選択肢 (画像は1
、動画は2
など) をハードコーディングすることですが、維持する必要があるため、エラーが発生しやすくなります。結局のところ、Django はコンテンツ タイプ フレームワークを使用してこれを解決します。何が起こるかというとsyncdb
、Django は、プロジェクト内にある各テーブル/モデルに一意の番号を割り当てます。私にとっては、それをテーブル タイプ ID と考える方が簡単です (テーブル自体には ID がないため、テーブル ID と仮定します)。したがって、この番号は後で特定のテーブルを参照するために使用できます。
次に、画像のコンテンツ タイプ (テーブル タイプ ID) が1
で、 pk を含むキーワードを pk7
を含む画像にリンクする場合は、次の11
方法で実行できます。
KeywordItem.objects.create(keyword_id=7,
content_type_id=1,
object_id=11)
# or using Django magic (this automatically figures out the content type):
KeywordItem.objects.create(keyword_id=7,
object=Image.objects.get(pk=11))
願わくば、これで一般的なリレーションが必要な理由の概念について少し説明できれば幸いです。では、GenericRelation
. 上記の例を使用して、特定の画像のすべてのキーワードにアクセスしたいとします。次のようなことをする必要があります:
img = Image.object.get(...)
img_type = ContentType.objects.get_for_model(img)
img_keywords = KeywordItem.objects.filter(content_type_id=img_type,
object_id=img.pk)
ただし、それはきれいに見えないため、GenericRelation
便利です。逆ジェネリック リレーションへのアクセスが非常に簡単になります。そのためには、次のフィールドをImage
モデルに追加する必要があります。
class Image(models.Model):
# ...
keywords = generic.GenericRelation('KeywordItem')
これで、次のようにするだけでキーワードにアクセスできるようになります。
Image.object.get(...).keywords.all()
注意事項
ジェネリック外部キーは、特に Django では構文がやや複雑なため、注意が必要です。あなたが Django の初心者である場合、Django で外部キーと Django が提供するすべての「魔法の」(たとえばrelated_name
パラメータ) を快適に操作できるようになるまで、それらを使用することはお勧めしません。それを理解すれば、一般的な外部キーは理解しやすく、使いやすくなります。