Django ContentType组件
一、作用
概念: contenttypes 是Django内置的一个应用,可以追踪项目中所有app和model的对应关系,并记录在ContentType表中
二、应用场景
一张多对一的表,与多张表有对应关系(多对一)
可以通过,给多对一的表添加字段来完成,没有用到的值用空值表示,但这种操作太过于麻烦
思想:
通过创建一张额外的表用于存储表名,
多对一的表
id .... xid(单表的id) oid(额外的表的id)
1 1 1
2 2 1
举例:
-不同种类的课程对应不同的表
-每一类课程,每一个课程,对应多种价格
三、知识点
1、导入模块
from django.db import models from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation # Create your models here.
2、在多对一的表中创建三个字段
# content_type 和 object_id 以及 content_object 的名称是固定的 content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE) # PositiveIntegerField 正整数 object_id = models.PositiveIntegerField() # 不会在数据库中生成字段, 只用于查询和添加 content_object = GenericForeignKey('content_type', 'object_id')
3、在一的表中添加
# policy_list不会在数据库生成,只用于查询 policy_list = GenericRelation(to="PricePolicy")
4、3个过程
a、在django_content_type中添加表的数据
b、多对一的表与一表产生联系
c、一的表与多对一的表产生联系
四、示例
1、models.py
from django.db import models from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation # Create your models here. class Course(models.Model): name = models.CharField(max_length=32, unique=True) img = models.CharField(max_length=255) # 不会在数据库中产生字段,只用于查询 policy_list = GenericRelation(to="PricePolicy") def __str__(self): return self.name class DegreeCourse(models.Model): name = models.CharField(max_length=32, unique=True) img = models.CharField(max_length=255) # policy_list不会在数据库生成,只用于查询 policy_list = GenericRelation(to="PricePolicy") def __str__(self): return self.name class PricePolicy(models.Model): # content_type 和 object_id 以及 content_object 的名称是固定的 content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE) # PositiveIntegerField 正整数 object_id = models.PositiveIntegerField() # 不会在数据库中生成字段, 只用于查询和添加 content_object = GenericForeignKey('content_type', 'object_id') valid_period_choices = ( (1, '1天'), (3, '3天'), (7, '1周'), (14, '2周'), (30, '1个月'), (60, '2个月'), (90, '3个月'), (180, '6个月'), (210, '12个月'), (540, '18个月'), (720, '24个月'), ) valid_period = models.SmallIntegerField(choices=valid_period_choices) price = models.FloatField()
2、views.py
from django.shortcuts import render, HttpResponse from app01.models import Course, DegreeCourse, PricePolicy # Create your views here. def test(request): # 1.添加数据: 先PricePolicy表中, 添加一条数据 # PricePolicy.objects.create( # valid_period=7, # price=88.22, # content_object=Course.objects.get(id=1) # ) # # 2.正向查找: 从PricePolicy表中, 查找对应表的数据 # price_obj = PricePolicy.objects.get(id=1) # course_name = price_obj.content_object.name # course_img = price_obj.content_object.img # print(course_name) # print(course_img) # 3.反向查找: 从Course表中,找到 在PricePolicy对应的数据 course_obj = Course.objects.get(pk=1) ret = course_obj.policy_list.all() li = [{'id': i.id, "价格": i.price, "周期": i.valid_period} for i in ret] print(li) return HttpResponse('ok')