什么是content type:django
内置的一个组件,这个组件帮忙做连表的操作。(混搭连表)
适用场景:适用于一张表与多张表同时做关联的时候。直接导入就可以使用了。
什么是Django ContentTypes
? Django ContentTypes
是由Django
框架提供的一个核心功能,它对当前项目中所有基于Django
驱动的model提供了更高层次的抽象接口。 当然我们不是说的是http
中的content-type
!完全没有任何关系!
下面将一步一步解释Django ContentTypes
在Django
框架中做了什么,以及如何使用Django ContentTypes
。
Django ContentTypes
做了什么?当使用django-admin
初始化一个django
项目的时候,可以看到在默认的INSTALL_APPS
已经包含了django.contrib.contenttypes
:
1 2 3 4 5 6 7 8 INSTALLED_APPS = [ 'django.contrib.admin' , 'django.contrib.auth' , 'django.contrib.contenttypes' , 'django.contrib.sessions' , 'django.contrib.messages' , 'django.contrib.staticfiles' , ]
而且注意django.contrib.contenttypes
是在django.contrib.auth
之后,这是因为auth
中的permission
系统是根据contenttypes
来实现的。
我们来查询查阅了一下django.contrib.contenttypes.models
文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 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' ),) def __str__ (self ): return self.name
大家可以看到ContentType
就是一个简单的django model
,而且它在数据库中的表的名字为django_content_type
。
这个表的名字一般都不会陌生,在第一次对Django
的model
进行migrate
之后,就可以发现在数据库中出现了一张默认生成的名为django_content_type
的表。
如果没有建立任何的model
,默认django_content_type
是这样的:
因此,django_content_type
记录了当前的Django
项目中所有model
所属的app
(即app_label
属性)以及model
的名字(即model
属性)。
当然,django_content_type
并不只是记录属性这么简单,contenttypes
是对model
的一次封装,
因此可以通过contenttypes
动态的访问model
类型,而不需要每次import
具体的model
类型。
Django ContentTypes
的使用场景ContentType
组件应用:在model
中定义ForeignKey
字段,并关联到ContentType
表,通常这个字段命名为content-type
在model
中定义PositiveIntergerField
字段, 用来存储关联表中的主键,通常我们用object_id
在model
中定义GenericForeignKey
字段,传入上面两个字段的名字 方便反向查询可以定义GenericRelation
字段 DEMO需求 现在我们有这样一个需求~我们的商城里有很多的商品,节日要来了,我们要搞活动。那么我们就要设计优惠券,优惠券都有什么类型呢,满减的、折扣的、立减的。 我们对应着我们活动类型,对我们的某类商品设计优惠券,比如:家电是一类商品、食物是一类商品。那么我们可以设计家电折扣优惠券,以及食物满减优惠券等…… 那么我们看表结构怎么设计???
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 class Coupon (models.Model): ''' 优惠券表 id name appliance_id food_id fruit_id 1 通用优惠券 null null null 2 冰箱折扣券 1 null null 3 电视折扣券 2 null null 4 苹果满减卷 null null 1 我每增加一张表就要多增加一个字段 ''' name = models.CharField(verbose_name='优惠券名' , max_length=50 ) def __str__ (self ): return self.name class Appliance (models.Model): ''' 家用电器表 id name 1 电视 2 冰箱 3 空调 ''' name = models.CharField(verbose_name='电器名称' , max_length=50 ) def __str__ (self ): return self.name class Food (models.Model): ''' 食物表 id name 1 面包 2 牛奶 3 零食 ''' name = models.CharField(verbose_name='食物名称' , max_length=50 ) def __str__ (self ): return self.name class Fruit (models.Model): ''' 水果表 id name 1 苹果 2 香蕉 3 西瓜 ''' name = models.CharField(verbose_name='水果名' , max_length=50 ) def __str__ (self ): return self.name
实际上我们商品的种类会特别的多,导致我们这张表外键越来越多遇到像Coupon
这种一张表要跟多张表进行外键关联的时候~我们Django
提供了ContentType
组件
使用ContentType
重置数据表 model数据表 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 from django.db import modelsfrom django.contrib.contenttypes.models import ContentTypefrom django.contrib.contenttypes.fields import GenericForeignKey, GenericRelationclass Coupon (models.Model): ''' 优惠券表 ''' name = models.CharField(verbose_name='优惠券名' , max_length=50 ) content_type = models.ForeignKey(to=ContentType, on_delete=models.CASCADE) object_id = models.PositiveIntegerField() content_object = GenericForeignKey('content_type' , 'object_id' ) def __str__ (self ): return self.name class Appliance (models.Model): ''' 家用电器表 id name 1 电视 2 冰箱 3 空调 ''' name = models.CharField(verbose_name='电器名称' , max_length=50 ) coupons = GenericRelation(to=Coupon) def __str__ (self ): return self.name class Food (models.Model): ''' 食物表 id name 1 面包 2 牛奶 3 零食 ''' name = models.CharField(verbose_name='食物名称' , max_length=50 ) def __str__ (self ): return self.name class Fruit (models.Model): ''' 水果表 id name 1 苹果 2 香蕉 3 西瓜 ''' name = models.CharField(verbose_name='水果名' , max_length=50 ) def __str__ (self ): return self.name
view视图文件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 from django.shortcuts import HttpResponsefrom app import modelsdef index (request ): content = models.ContentType.objects.filter (app_label='app' , model='appliance' ).first() model_class = content.model_class() obj_list = model_class.objects.all () obj = models.Appliance.objects.filter (pk=3 ).first() models.Coupon.objects.create(name='618洗衣机优惠券' , content_object=obj) coupon_obj = models.Coupon.objects.filter (pk=1 ).first() good = coupon_obj.content_object good_obj = models.Appliance.objects.filter (pk=3 ).first() coupon_objs = good_obj.coupons.all () coupon_objs = models.Coupon.objects.filter (content_type=content, object_id=3 ) return HttpResponse('ok' )