一、什么是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:

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

  2、关于django.contrib.contenttypes.models文件:

  1. class ContentType(models.Model):
  2. app_label = models.CharField(max_length=100)
  3. model = models.CharField(_('python model class name'), max_length=100)
  4. objects = ContentTypeManager()
  5. class Meta:
  6. verbose_name = _('content type')
  7. verbose_name_plural = _('content types')
  8. db_table = 'django_content_type'
  9. unique_together = (('app_label', 'model'),)
  10. def __str__(self):
  11. return self.name
    注释:可以看出ContentType就是一个简单的django model,而且它在数据库中的表的名字为django_content_type

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

如果没有建立任何的model,默认django_content_type是这样的:

  1. sqlite> select * from django_content_type;
  2. 1|admin|logentry
  3. 2|auth|group
  4. 3|auth|user
  5. 4|auth|permission
  6. 5|contenttypes|contenttype
  7. 6|sessions|session
  8.  
  9. 注释:1django_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. 1ContentType实例提供的接口
  2. ContentType.model_class() # 获取当前ContentType类型所代表的模型类
  3. ContentType.get_object_for_this_type() #使用当前ContentType类型所代表的模型类做一次get查询
  4.  
  5. 2ContentType管理器(manager)提供的接口
  6. ContentType.objects.get_for_id() #通过id寻找ContentType类型,这个跟传统的get方法的区别就是它跟get_for_model共享一个缓存,因此更为推荐。
  7. 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 实例所表示的模型类。

    示例:

  1. 例如,我们可以查找User 模型的ContentType
  2.  
  3. >>> from django.contrib.contenttypes.models import ContentType
  4. >>> user_type = ContentType.objects.get(app_label="auth", model="user")
  5. >>> user_type
  6. <ContentType: user>
  7.  
  8. 然后使用它来查询一个特定的User,或者访问 User 模型类︰
  9.  
  10. >>> user_type.model_class()
  11. <class 'django.contrib.auth.models.User'>
  12. >>> user_type.get_object_for_this_type(username='Guido')
  13. <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的通用类型  
  假设以下的应用场景:

  1. 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
  2.  
  3. 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="优惠券介绍")
  4.  
  5. # 那个表?
    content_type = models.ForeignKey(ContentType, blank=True, null=True)
    # 对象ID
    object_id = models.PositiveIntegerField("绑定课程", blank=True, null=True, help_text="可以把优惠券跟课程绑定")
  6.  
  7. content_object = GenericForeignKey('content_type', 'object_id')
      #content_object = fields.GenericForeignKey() #应该可以这么写
  8.  
  9. 注释:ContentType提供了一种GenericForeignKey的类型,通过这种类型可以实现在Comment对其余所有model的外键关系。
       一张表和其他多个表管理,并创建多个FK时,并且多个Fk只能选择其中一个时,可以用ContentType
       通过使用一个content_type属性代替了实际的model,而object_id则代表了实际model中的一个实例的主键,其中,content_typeobject_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. Javascript代码执行过程-《悟透Javascript》笔记

    本文摘录自李战老师<悟透Javascript>一书的部分章节,为适应博客发表作了一点点修改. 1) 预编译分析. JavaScript执行引擎将所有定义式函数直接创建为作用域上的函数变量, ...

  2. Unity UGUI实现Button按钮长按状态的判断

    代码: using UnityEngine.EventSystems; using System.Collections; /// <summary> /// 脚本位置:UGUI按钮组件身 ...

  3. hdu 3336:Count the string(数据结构,串,KMP算法)

    Count the string Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) ...

  4. C语言的代码内存布局详解

    一个程序本质上都是由 BSS 段.data段.text段三个组成的.这样的概念在当前的计算机程序设计中是很重要的一个基本概念,而且在嵌入式系统的设计中也非常重要,牵涉到嵌入式系统运行时的内存大小分配, ...

  5. windows系统添加服务命令

    管理员身份进入cmd sc create TestSvr binPath= D:\Program Files\test.exe start= auto

  6. 【BZOJ1050】[HAOI2006]旅行comf 并查集

    [BZOJ1050][HAOI2006]旅行comf Description 给你一个无向图,N(N<=500)个顶点, M(M<=5000)条边,每条边有一个权值Vi(Vi<300 ...

  7. java利用反射机制判断对象的属性是否为空以及获取和设置该属性的值

    1.java利用反射机制判断对象的属性是否为空: Map<String,String> validateMap = new LinkedHashMap<String, String& ...

  8. msvcp71.dll 怎么丢失的?如何修复

    解决方法:另一台电脑上下载这个dll,再用优盘拷回来,复制到c:\windows\system32\下. 个人遇到的情况:迅雷下载东西时,或者在操作迅雷时出现的. win7 64位下 点击下载

  9. 160323、理解Java虚拟机体系结构

    今天看到一篇文章,觉得写得不错,特拿来跟大家分享一下 1 概述 众所周知,Java支持平台无关性.安全性和网络移动性.而Java平台由Java虚拟机和Java核心类所构成,它为纯Java程序提供了统一 ...

  10. 如何给MFC的菜单项添加快捷键

    我们一起分享,如何给MFC的菜单项添加快捷键.[程序在VC6.0编译环境下编译通过.(VS2010的编译环境大同小异)] 1.程序演示环境 1.1新建一个[对话框(Dialog)]的程序.然后,New ...