Django contenttype
Django ContentTypes是由Django框架提供的一个核心功能,它对当前项目中所有基于Django驱动的model提供了更高层次的抽象封装。
当使用Django-admin初始化一个django项目的时候,可以看到在默认的INSTALL_APPS已经包含了django.contrib.contenttypes:
1 INSTALLED_APPS = [ 2 'django.contrib.admin', 3 'django.contrib.auth', 4 'django.contrib.contenttypes', 5 'django.contrib.sessions', 6 'django.contrib.messages', 7 'django.contrib.staticfiles', 8 ]
使用背景:最近设计表的时候遇到一个问题,有两门课程 一门专业课,一门学位课,我们按照时间长度来进行售卖,比如专业课一个月19元,两个月35元,三个月50元。
可以这么做但是领导不让我这么设计。。。。。。
所以就想着用第三章表来实现需求
这是Django中自带的ContentType这张表中就有我创建的那三张表(学位课表,专业课表,价格策略表),所以表结构如下
1 from django.db import models 2 3 # Create your models here. 4 5 6 from django.db import models 7 from django.contrib.contenttypes.models import ContentType 8 from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation 9 10 11 class DegreeCourse(models.Model): 12 name = models.CharField(max_length=32) 13 14 15 class Course(models.Model): 16 name = models.CharField(max_length=32) 17 18 # 数据库不生成,只用于链表查询 19 policy_list = GenericRelation("PricePolicy") 20 21 22 class PricePolicy(models.Model): 23 content_type = models.ForeignKey(ContentType) 24 object_id = models.PositiveIntegerField() 25 26 # 不在数据库中生成,只用于帮助你做数据操作 27 content_object = GenericForeignKey('content_type', 'object_id') 28 29 period = models.CharField(max_length=32) 30 price = models.FloatField() 31 32 model.py
1 def index(request): 2 course_obj = Course.objects.get(id=2) 3 #从PricePolicy创建数据 content_obj 是GenericForeignKey 便于操作直接赋予对象即可 4 PricePolicy.objects.create(period='110', price=9.9, content_object=course_obj) 5 PricePolicy.objects.create(period='120', price=19.9, content_object=course_obj) 6 PricePolicy.objects.create(period='130', price=29.9, content_object=course_obj) 7 price_list = PricePolicy.objects.all() 8 9 for priceplicy in price_list: 10 # 取出一个个的models对象 . content_obj 就可以去到相对应的 11 print(priceplicy.content_object.name,priceplicy.price, priceplicy.period) 12 #通过Course对象,获取对用的所有价格 13 course_obj = Course.objects.get(id=1) 14 obj = course_obj.policy_list.filter(id=3) 15 objs = course_obj.policy_list.all() 16 17 print(obj) 18 return HttpResponse('ok') 19 20 views.py
总结:
GenericRelation和GenericForeignKey实现了双向查找
当一张表作为多个表的FK,并且只能选择其中一个或者几个时,就可以使用content_type表;例如上面的优惠券表,被食物和衣服当作FK,数据库表一旦建立就难以更改,如果以后需要增加电器等表并把优惠券表作为FK表,这时就不能做到在优惠券表增加列字段electr_id,因为表只能增加行记录而不能增加列字段,因此就可以使用content_type表来将表与表中的对象进行关联,从而做到不增加列字段的情况下增加FK关系。
在使用content_type表时,需要在FK表中增加content_type作为FK字段,并增加GenericForeignKey便于优惠券表记录的建立以及单个优惠券对象对应的其他商品的查找。在优惠券表关联的“一”的关系表中增加GenericRelation字段便于查找关联的优惠券记录的查找