一、什么是Django ContentTypes?

  1、Django 包含一个ContentTypes 应用,它可以追踪安装在你的Django 项目里的所有应用,并提供一个高层次的、通用的接口用于与你的模型进行交互。

  2、Django ContentTypes是由Django框架提供的一个核心功能,它对当前项目中所有基于Django驱动的model提供了更高层次的抽象接口。

  3、Contenttypes 的核心应用是ContentType模型,存在于 django.contrib.contenttypes.models.ContentType。ContentType 的实例表示并存储你的项目当中安装的应用的信息,并且每当新的模型安装时会自动创建新的 ContentType 实例。

  4、ContentType  实例具有返回它们表示的模型类的方法,以及从这些模型查询对象的方法。ContentType 还有一个自定义的管理器用于添加方法来与ContentType工作,以及用于获得ContentType实例的特定模型。

  5、你的模型和ContentType 之间的关系还可以用于一个模型实例和任意一个已经安装的模型的实例建立“generic关联”。

二、Django ContentTypes做了什么?

  1、当使用django-admin初始化一个django项目的时候,可以看到在默认的INSTALL_APPS已经包含了django.contrib.contenttypes:

INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
注释:1、注意django.contrib.contenttypes是在django.contrib.auth之后,这是因为auth中的permission系统是根据contenttypes来实现的。
   2、Contenttypes 框架包含在django-admin startproject 创建的默认的INSTALLED_APPS列表中  
   3、Admin 应用使用它来记录通过Admin 界面添加或更改每个对象的历史。
   4、Django 的authentication 框架用它来授用户权限给特殊的模型。

  2、关于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。

  3、有经验的Django开发者对于这个表的名字一般都不会陌生,在第一次对Django的model进行migrate之后,就可以发现在数据库中出现了一张默认生成的名为django_content_type的表。

如果没有建立任何的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 注释:1、django_content_type记录了当前的Django项目中所有model所属的app(即app_label属性)以及model的名字(即model属性)。
   2、每一个ContentType 实例有两个字段,共同来唯一描述一个已经安装的模型。
     app_label:模型所在的应用的名称。 这取自模型的app_label 属性,并只包括应用的Python 导入路径的最后的部分。例如,"django.contrib.contenttypes"的app_label 是"contenttypes"。
     model:模型的类的名称。

  4、django_content_type并不只是记录属性这么简单,contenttypes其实是对model的一次封装,因此可以通过contenttypes动态的访问model类型,而不需要每次import具体的model类型。

1、ContentType实例提供的接口
ContentType.model_class() # 获取当前ContentType类型所代表的模型类
ContentType.get_object_for_this_type() #使用当前ContentType类型所代表的模型类做一次get查询 2、ContentType管理器(manager)提供的接口
ContentType.objects.get_for_id() #通过id寻找ContentType类型,这个跟传统的get方法的区别就是它跟get_for_model共享一个缓存,因此更为推荐。
ContentType.objects.get_for_model() #接收一个模型类或模型的实例,并返回表示该模型的ContentType实例
    ContentType.objects.get_for_models()

三、Django ContentTypes的使用方法

  1、每一个 ContentType 都有一些方法允许你用ContentType实例来到达它所代表的model, 或者从model取出对象:

    ContentType.get_object_for_this_type(**kwargs)[source]   #接收ContentType 表示的模型所接收的查询参数,对该模型做一次get() 查询,然后返回相应的对象。
    ContentType.model_class()[source]   #返回此ContentType 实例所表示的模型类。

    示例:

例如,我们可以查找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>

  2、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

get_by_natural_key(app_label, model)#返回由给定的应用标签和模型名称唯一标识的ContentType 实例。这种方法的主要目的是为允许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')
  #content_object = fields.GenericForeignKey() #应该可以这么写 注释:ContentType提供了一种GenericForeignKey的类型,通过这种类型可以实现在Comment对其余所有model的外键关系。
   一张表和其他多个表管理,并创建多个FK时,并且多个Fk只能选择其中一个时,可以用ContentType。
   通过使用一个content_type属性代替了实际的model,而object_id则代表了实际model中的一个实例的主键,其中,content_type和object_id的字段命名都是作为字符串参数传进content_object的。

django内置 Contenttypes 框架的更多相关文章

  1. 框架----Django内置Admin

    Django内置的Admin是对于model中对应的数据表进行增删改查提供的组件,使用方式有: 依赖APP: django.contrib.auth django.contrib.contenttyp ...

  2. Django内置Admin

    Django内置的Admin是对于model中对应的数据表进行增删改查提供的组件,使用方式有: 依赖APP: django.contrib.auth django.contrib.contenttyp ...

  3. Django内置信号

    阅读目录(Content) Django中内置的signal 自定义信号 1.定义信号 2.注册信号 3.触发信号 回到顶部(go to top) Django中内置的signal Django中提供 ...

  4. Django内置Admin解析

    Django 内置的admin是对于model中对应的数据表进行增删改查提供的组建 一.Django admin的内部依赖: 依赖的app django.contrib.auth django.con ...

  5. django 内置“信号”机制和自定义方法

    一.引子 在操作数据的时候,假设我们需要记录一些日志,这个时候,我们需要用什么来显示这个需求呢?装饰器?装饰器只能先实现整体的操作.在django 里面有这么一个东西--信号 下面我们就来了解了解它. ...

  6. Django内置分页

    一.django内置分页 from django.shortcuts import render from django.core.paginator import Paginator, EmptyP ...

  7. Django 内置分页器

    先导入Django内置的分页器 在商品列表页或者购物车列表页导入 在渲染list.html导入 然后在views后台渲染方法写入 打开list页面结果

  8. Django内置权限扩展案例

    当Django的内置权限无法满足需求的时候就自己扩展吧~ 背景介绍 overmind项目使用了Django内置的权限系统,Django内置权限系统基于model层做控制,新的model创建后会默认新建 ...

  9. Spark2.1.0——内置Web框架详解

    Spark2.1.0——内置Web框架详解 任何系统都需要提供监控功能,否则在运行期间发生一些异常时,我们将会束手无策.也许有人说,可以增加日志来解决这个问题.日志只能解决你的程序逻辑在运行期的监控, ...

随机推荐

  1. 数据库 proc编程七

    #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include <stri ...

  2. Hadoop源码分析之数据节点的握手,注册,上报数据块和心跳

    转自:http://www.it165.net/admin/html/201402/2382.html 在上一篇文章Hadoop源码分析之DataNode的启动与停止中分析了DataNode节点的启动 ...

  3. 第二百七十九节,MySQL数据库-pymysql模块操作数据库

    MySQL数据库-pymysql模块操作数据库 pymysql模块是python操作数据库的一个模块 connect()创建数据库链接,参数是连接数据库需要的连接参数使用方式: 模块名称.connec ...

  4. java内存溢出怎么解决

    java.lang.OutOfMemoryError这个错误我相信大部分开发人员都有遇到过,产生该错误的原因大都出于以下原因:JVM内存过小.程序不严密,产生了过多的垃圾. 导致OutOfMemory ...

  5. 【BZOJ】1616: [Usaco2008 Mar]Cow Travelling游荡的奶牛(dp/-bfs)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1616 我觉得bfs是可过的,但是交bfs上去是wa? 然后没办法看dp,原来这bfs能和dp联系在一 ...

  6. ie中自动识别单屏与双屏(js)

    <!DOCTYPE html> <html> <head> <meta name="viewport" content="wid ...

  7. CSS之各种居中

    本博客讨论居中情况设定为 总宽度不定,内容宽度不定 的情况.(改变大小时,仍然居中). 特别说明:在元素设置 position:absolute; 来设置居中效果时,除去博客下介绍的css3方法外,还 ...

  8. iOS开发之-- oc 和 swift混编之自建桥接文件

    进行swift开发的时候,oc 的项目已经进行了很长一段时间,所以默认使用Xcode自建的桥接文件的时候,这个桥接文件名称是固定的,放置的目录也是无法更改的,所以我就想自己创建一个桥接文件,然后在ta ...

  9. VS2010类模板更改,增加版权等等信息

    本文转载自XDOTNET 在开发过程中往往需要在每一个页面(类)增加注释等等内容,VS2010中可以修改模板,在原有模板中增加一个类,会引用System等等命名空间,以及一些程序集.下面我们来看看如何 ...

  10. 【黑金原创教程】【TimeQuest】【第六章】物理时钟与外部模型

    声明:本文为黑金动力社区(http://www.heijin.org)原创教程,如需转载请注明出处,谢谢! 黑金动力社区2013年原创教程连载计划: http://www.cnblogs.com/al ...