7. 如何创建可与任何实体相关联的通用模型(如类别或评论)?

有模型如下:

class Category(models.Model):
    name = models.CharField(max_length=100)
    # ...

    class Meta:
        verbose_name_plural = "Categories"


class Hero(models.Model):
    name = models.CharField(max_length=100)
    category = models.ForeignKey(Category, on_delete=models.CASCADE)
    # ...


class Villain(models.Model):
    name = models.CharField(max_length=100)
    category = models.ForeignKey(Category, on_delete=models.CASCADE)
    # ...

可被应用的 Category 是一个通用模型。你可能想要从任何的模型类应用类别到对象。你可以这样做:

from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
# ...

class FlexCategory(models.Model):
    name = models.SlugField()
    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
    object_id = models.PositiveIntegerField()
    content_object = GenericForeignKey('content_type', 'object_id')


class Hero(models.Model):
    name = models.CharField(max_length=100)
    flex_category = GenericRelation(FlexCategory, related_query_name='flex_category')
    # ...


class Villain(models.Model):
    name = models.CharField(max_length=100)
    flex_category = GenericRelation(FlexCategory, related_query_name='flex_category')
    # ...

我们使用 ForeignKeyPositiveIntegerFieldFlexCategory 添加了 GenericForeignKey ,然后在你想要类别化的模型上添加了 :code:`GenericRelation 。

在数据库上类似这样:

你可以这样类别化 Hero

FlexCategory.objects.create(content_object=hero, name="mythic")

然后得到名为ghost的类别化后的 Hero.

FlexCategory.objects.create(content_object=hero, name="ghost")

SQL语句如下

SELECT "entities_hero"."name"
FROM "entities_hero"
INNER JOIN "entities_flexcategory" ON ("entities_hero"."id" = "entities_flexcategory"."object_id"
                                       AND ("entities_flexcategory"."content_type_id" = 8))
WHERE "entities_flexcategory"."name" = ghost