Q
null=True
blank=True
#django #tutorial #orm
Originalhttps://books.agiliq.com/projects/django-orm-cookbook/en/latest/
You have models like this.
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 can be applied as a generic model. You prbably want to be able to apply categories to objects form any model class. You can do it like this
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') # ...
What did we do, we added a GenericForeignKey fields on FlexCategory using one ForeignKey and one PositiveIntegerField, then added a GenericRelation on the models you want to categorize.
GenericForeignKey
FlexCategory
ForeignKey
PositiveIntegerField
GenericRelation
At the database level it looks like this:
You can categorize a Hero like this.
Hero
FlexCategory.objects.create(content_object=hero, name="mythic")
And then get a Hero categorised as ‘ghost’ like this
FlexCategory.objects.create(content_object=hero, name="ghost")
This gives us this 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