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组件的设计可以帮助我们很好的应景一张表关联多张表,虽然操作简单,表的数量较少,但是却牺牲了查询效率

posted on 2023-02-27 21:54  阿明明  阅读(23)  评论(0编辑  收藏  举报