1

誰かがこれを書いたmodels.py

documents = generic.GenericRelation(Document)

ForeignKeyOneToManyフィールドのような他のタイプとどう違うのか知りたいです。

これに関する十分なドキュメントを見たことがない

ここで何かを見つけたら

しかし、最初から contenttype が何をするのか、そしてなぜそれを使うのか理解していません。

4

1 に答える 1

3

データベースにさまざまなオブジェクト (画像、ビデオ、曲など) があり、それぞれにキーワードを追加したいとします。ただし、キーワードを持つすべてのオブジェクトのすべてのキーワードを管理する単一のキーワード テーブルが必要です。したがって、モデルは次のようになります。

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パラメータ) を快適に操作できるようになるまで、それらを使用することはお勧めしません。それを理解すれば、一般的な外部キーは理解しやすく、使いやすくなります。

于 2012-10-15T04:20:06.080 に答える