Contenttypes是一个app,将Django中的所有定义的表定义在一张表中
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', # **** # 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', "app01.apps.App01Config", "rest_framework" ]
在这个表中最开始保存着每个app的名字和模型类的小写,两者拼接就是数据库中表的名字,如app01_student
使用场景
当一张表关联多张表的时候就可以很好的发挥这个组件的作用了,下面通过一个案例来展示
假如有以下两张表
我们希望学位表和课程表中的课程都有不同时间对应的的价格,我们可以很好的想到如下方法
为课程表和学位表再各自创建一个表,实现二者的关系,虽然功能上可以实现,但会产生很多的表
我们可以可改进如下
虽然表的数量减少了,但是会产生很多的NUll字段
我们就可以使用contenttypes 表
代码展示
模型类
from django.db import models # Create your models here. from django.db import models from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation from django.contrib.contenttypes.models import ContentType class DegreeCourse(models.Model): """学位课程""" name = models.CharField(max_length=128, unique=True) class Course(models.Model): """课程""" name = models.CharField(max_length=128, unique=True) class PricePolicy(models.Model): """价格与有课程效期表""" content_type_id = models.ForeignKey(ContentType, on_delete=models.CASCADE) object_id = models.PositiveIntegerField() time = models.CharField(verbose_name="时间段", max_length=32) price = models.IntegerField(verbose_name="价格")
添加数据
def func(request): models.PricePolicy.objects.create( content_type_id=9, # 对应着django_content_type中 degreecourse表id object_id=1, # degreecourse表中的id=1的对象 time="3个月", price=100, ) models.PricePolicy.objects.create( content_type_id=8, object_id=2, time="6个月", price=300 )
但是我们还需要去contenttypes表中去寻找表的id和数据行的id,我们修改代码如下
模型类
from django.db import models # Create your models here. from django.db import models from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation from django.contrib.contenttypes.models import ContentType class DegreeCourse(models.Model): """学位课程""" name = models.CharField(max_length=128, unique=True) class Course(models.Model): """课程""" name = models.CharField(max_length=128, unique=True) class PricePolicy(models.Model): """价格与有课程效期表""" content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE) object_id = models.PositiveIntegerField() # 在数据库中不会创建该字段 content_type_object = GenericForeignKey("content_type", "object_id") time = models.CharField(verbose_name="时间段", max_length=32) price = models.IntegerField(verbose_name="价格")
添加数据
models.PricePolicy.objects.create( content_type_object=models.DegreeCourse.objects.filter(name="linux").first(), time="3个月", price=100, )
查找数据
- 正向查询
for item in models.PricePolicy.objects.all(): print(item.time, item.price, item.content_type_object,item.content_type_object.name)
结果
3个月 100 DegreeCourse object (1) python全栈 6个月 300 Course object (2) Django项目 3个月 100 DegreeCourse object (3) linux
- 反向查询
需要将模型类代码修改为
from django.db import models # Create your models here. from django.db import models from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation from django.contrib.contenttypes.models import ContentType class DegreeCourse(models.Model): """学位课程""" name = models.CharField(max_length=128, unique=True) degree_price = GenericRelation(to="PricePolicy") class Course(models.Model): """课程""" name = models.CharField(max_length=128, unique=True) course_price = GenericRelation(to="PricePolicy") class PricePolicy(models.Model): """价格与有课程效期表""" content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE) object_id = models.PositiveIntegerField() # 在数据库中不会创建该字段 content_type_object = GenericForeignKey("content_type", "object_id") time = models.CharField(verbose_name="时间段", max_length=32) price = models.IntegerField(verbose_name="价格")
查询代码
obj = models.DegreeCourse.objects.filter(name="linux").first() for item in obj.degree_price.all(): print(item.price, item.time)
contenttype组件的设计可以帮助我们很好的应景一张表关联多张表,虽然操作简单,表的数量较少,但是却牺牲了查询效率