1、什么是Django ContentTypes?html
一、Django 包含一个ContentTypes 应用,它能够追踪安装在你的Django 项目里的全部应用,并提供一个高层次的、通用的接口用于与你的模型进行交互。python
二、Django ContentTypes是由Django框架提供的一个核心功能,它对当前项目中全部基于Django驱动的model提供了更高层次的抽象接口。sql
三、Contenttypes 的核心应用是ContentType模型,存在于 django.contrib.contenttypes.models.ContentType。ContentType 的实例表示并存储你的项目当中安装的应用的信息,而且每当新的模型安装时会自动建立新的 ContentType 实例。数据库
四、ContentType 实例具备返回它们表示的模型类的方法,以及从这些模型查询对象的方法。ContentType 还有一个自定义的管理器用于添加方法来与ContentType工做,以及用于得到ContentType实例的特定模型。django
五、你的模型和ContentType 之间的关系还能够用于一个模型实例和任意一个已经安装的模型的实例创建“generic关联”。缓存
2、Django ContentTypes作了什么?session
一、当使用django-admin初始化一个django项目的时候,能够看到在默认的INSTALL_APPS已经包含了django.contrib.contenttypes:app
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来实现的。
二、Contenttypes 框架包含在django-admin startproject 建立的默认的INSTALLED_APPS列表中
三、Admin 应用使用它来记录经过Admin 界面添加或更改每一个对象的历史。
四、Django 的authentication 框架用它来授用户权限给特殊的模型。
二、关于django.contrib.contenttypes.models文件:框架
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开发者对于这个表的名字通常都不会陌生,在第一次对Django的model进行migrate以后,就能够发如今数据库中出现了一张默认生成的名为django_content_type的表。ide
若是没有创建任何的model,默认django_content_type是这样的:
sqlite> select * from django_content_type; 1|admin|logentry 2|auth|group 3|auth|user 4|auth|permission 5|contenttypes|contenttype 6|sessions|session
注释:一、django_content_type记录了当前的Django项目中全部model所属的app(即app_label属性)以及model的名字(即model属性)。
二、每个ContentType 实例有两个字段,共同来惟一描述一个已经安装的模型。
app_label:模型所在的应用的名称。 这取自模型的app_label 属性,并只包括应用的Python 导入路径的最后的部分。例如,"django.contrib.contenttypes"的app_label 是"contenttypes"。
model:模型的类的名称。
四、
django_content_type并不仅是记录属性这么简单,contenttypes实际上是对model的一次封装,所以能够经过contenttypes动态的访问model类型,而不须要每次import具体的model类型。
一、ContentType实例提供的接口 ContentType.model_class() # 获取当前ContentType类型所表明的模型类 ContentType.get_object_for_this_type() #使用当前ContentType类型所表明的模型类作一次get查询
二、ContentType管理器(manager)提供的接口 ContentType.objects.get_for_id() #经过id寻找ContentType类型,这个跟传统的get方法的区别就是它跟get_for_model共享一个缓存,所以更为推荐。 ContentType.objects.get_for_model() #接收一个模型类或模型的实例,并返回表示该模型的ContentType实例
ContentType.objects.get_for_models()
3、Django ContentTypes的使用方法
一、每个 ContentType 都有一些方法容许你用ContentType实例来到达它所表明的model, 或者从model取出对象:
示例:
例如,咱们能够查找User 模型的ContentType︰
>>> from django.contrib.contenttypes.models import ContentType
>>> user_type = ContentType.objects.get(app_label="auth", model="user")
>>> user_type
<ContentType: user>
而后使用它来查询一个特定的User,或者访问 User 模型类︰
>>> user_type.model_class()
<class 'django.contrib.auth.models.User'>
>>> user_type.get_object_for_this_type(username='Guido')
<User: Guido>
二、ContentTypeManager(自定义的管理器ContentTypeManager)
clear_cache() #清除ContentType 用于跟踪模型的内部缓存,它已为其建立ContentType 实例。你可能不须要本身调用此方法;Django 将在它须要的时候自动调用。
get_for_id(id) #经过ID查找ContentType。因为此方法使用与get_for_model() 相同的共享缓存,建议使用这个方法而不是一般的 ContentType.objects.get(pk=id)
get_for_model(model[, for_concrete_model=True])#接收一个模型类或模型的实例,并返回表示该模型的ContentType 实例。for_concrete_model=False 容许获取代理模型的ContentType
get_for_models(*models[, for_concrete_models=True])#接收可变数目的模型类,并返回一个字典,将模型类映射到表示它们的ContentType 实例。for_concrete_model=False 容许获取代理模型的ContentType。
四
、ContentType的通用类型
假设如下的应用场景:
class Coupon(models.Model):
"""优惠券生成规则
ID 优惠券名称 A FK B.FK c.FK
1 通用 null null
2 满100-10 8 1
3 满200-30 8 2
4 满200-30 9 1
ID 优惠券名称 content_type_id(表) object_id(表中数据ID)
1 通用 null null
2 满100-10 8 1
3 满200-30 8 2
4 满200-30 9 1
总结:
"""
name = models.CharField(max_length=64, verbose_name="活动名称")
brief = models.TextField(blank=True, null=True, verbose_name="优惠券介绍")
# 那个表?
content_type = models.ForeignKey(ContentType, blank=True, null=True)
# 对象ID
object_id = models.PositiveIntegerField("绑定课程", blank=True, null=True, help_text="能够把优惠券跟课程绑定")
content_object = GenericForeignKey('content_type', 'object_id')
#注释:ContentType提供了一种GenericForeignKey的类型,经过这种类型能够实如今Comment对其他全部model的外键关系。 一张表和其余多个表管理,并建立多个FK时,而且多个Fk只能选择其中一个时,能够用ContentType。 经过使用一个content_type属性代替了实际的model,而object_id则表明了实际model中的一个实例的主键,其中,content_type和object_id的字段命名都是做为字符串参数传进content_object的。
content_object = fields.GenericForeignKey() #应该能够这么写