Django中的contenttype表
contenttype
在Django中有一张表记录着app和该app下的类(即表)对应关系的一张表,就是contenttype表,
contenttype部分源码
在这里进入
from django.contrib.contenttypes.models import ContentType
class ContentType(models.Model): app_label = models.CharField(max_length=100) model = models.CharField(_('python model class name'), max_length=100) objects = ContentTypeManager() class Meta: verbose_name = _('content type') verbose_name_plural = _('content types') db_table = 'django_content_type' unique_together = (('app_label', 'model'),)
为什么会出现这张表呢?
首先,我们有这种场景
应用场景:某一在线教育网,需要为每位积极客户发一些观看视频的优惠券,但是,对于不同类型的视频,优惠券是不同。比如:有一个普通课程,需要发一些满200减30的优惠券,而又有精品课程,需要发满100键70的优惠券。根据以上需求,我们很快就知道,需要三张表,学位课程表,课程表以及优惠券表,那么,这三张表又是如何关联的呢?
A 学位课程表结构 # ID 名称 # 1 学位课1 # 2 学位课2 #B普通课程表 #ID 名称 #1 普通课1 #2 普通课2 #优惠券表 #ID 优惠券名称 A(FK) B(FK) #1 通用优惠券 null null # 两个都为空,说明全场都可以使用 #2 满100-10 1 null # 给学位课程创建优惠券 #3 满200-30 null 1 # 给普通课程创建优惠券
你这样做是没有问题的,但是你想想,如果我要新添加一个课程表,这时候在关联优惠券表这时候该怎么办呢, 增加字段是我们设计数据库的大忌讳,所以这时候contenttype表就出现了
from django.db import models # Create your models here. from django.db import models from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.fields import GenericForeignKey,GenericRelation class DegreeCourse(models.Model): name = models.CharField(max_length=32) policy_list = GenericRelation("PricePolicy") class Course(models.Model): name = models.CharField(max_length=32) # 数据库不生成,只用于链表查询不产生字段 policy_list = GenericRelation("PricePolicy") class PricePolicy(models.Model): Couponname = models.CharField(max_length=32) content_type = models.ForeignKey(ContentType) #外键关联contenttype表 object_id = models.PositiveIntegerField() #每张表中每条记录的主键id # 不在数据库中生成,只用于做正向查询数据操作 content_object = GenericForeignKey('content_type', 'object_id') price = models.FloatField()
views.py
from django.shortcuts import render,HttpResponse # Create your views here. from app02.models import * def add(request): ##只能这样来添加pricepolicy的数据 obj=DegreeCourse.objects.get(id=1) PricePolicy.objects.create(Couponname="满100减20",content_object=obj,price=1126) return HttpResponse("ok") def index(request): #查看某课程绑定的所有优惠券 obj=Course.objects.get(id=1) # obj=Course.objects.get(id=1) print(obj.policy_list.all().values("")) # print(obj.content_object.name)
#查询某个优惠券所有绑定的课程
obj1=PricePolicy.objects.get(id=1)
courses=obj1.content_object
return HttpResponse("ok")
GenericRelation
degreecourse 使用genericRelation来指向它的model实例,degreecourse中的实例可以根据这个字段来找到pricepolice中对应的所有记录,
GenericForeignKey
在Django中如何定位一条记录? 需要3个值来定位: Appname,model,object,其中Appname,model contenttype表中都已经给定义了,还剩下一个object,就需要generiForeignkey来定义了
这就是为什么generiforeignkey()有两个值的原因了
总结:
当一张表作为多个表的FK,并且只能选择其中一个或者几个时,就可以使用content_type表;例如上面的优惠券表,被食物和衣服当作FK,数据库表一旦建立就难以更改,如果以后需要增加电器等表并把优惠券表作为FK表,这时就不能做到在优惠券表增加列字段electr_id,因为表只能增加行记录而不能增加列字段,因此就可以使用content_type表来将表与表中的对象进行关联,从而做到不增加列字段的情况下增加FK关系。
在使用content_type表时,需要在FK表中增加content_type作为FK字段,并增加GenericForeignKey便于优惠券表记录的建立以及单个优惠券对象对应的其他商品的查找。在优惠券表关联的“一”的关系表中增加GenericRelation字段便于查找关联的优惠券记录的查找
公众号 种树飞编程 欢迎关注

浙公网安备 33010602011771号