一、什么是Django ContentTypes?

Django ContentTypes是由Django框架提供的一个核心功能,它对当前项目中所有基于Django驱动的model提供了更高层次的抽象接口。 当然我们不是说的是http中的content-type!完全没有任何关系!
下面将一步一步解释Django ContentTypes在Django框架中做了什么,以及如何使用Django ContentTypes。 
当然,如果对于ContentTypes有了初步了解而只是不了解它的应用场景,可以直接查阅一下原文档:

https://docs.djangoproject.com/en/1.10/ref/contrib/contenttypes/

二、Django ContentTypes做了什么?

当使用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',
]

而且注意django.contrib.contenttypes是在django.contrib.auth之后,这是因为auth中的permission系统是根据contenttypes来实现的。

我们来查询查阅了一下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的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类型。

    • 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() 
        • 通过model或者model的实例来寻找ContentType类型

三、Django ContentTypes的使用场景

在我们这个项目中各种商品的优惠卷就运用到了这个知识点:

假使我们models下有这几张表:

class Electrics(models.Model):  #电器类
name = models.CharField(max_length=32)
price= models.IntegerField(default=100) def __str__(self):
return self.name class Foods(models.Model): #食物类
name = models.CharField(max_length=32)
price = models.IntegerField(default=100) def __str__(self):
return self.name class Clothes(models.Model): #衣服类
name = models.CharField(max_length=32)
price= models.IntegerField(default=100)
def __str__(self):
return self.name class Coupon(models.Model): #优惠券
name = models.CharField(max_length=32) def __str__(self):
return self.name

我们先来考虑一个问题,如何把这些商品和优惠卷相关联?

一种商品一个优惠卷,那我们就在表中加入一种商品的优惠券,就是一个一对多的ForeignKey,那么多个商品就有各种优惠卷,

但是一种商品的特定优惠卷在表结构中,就那个字段有值,别的不相关的记录为null,而且每增加一个商品,又要手动的去添加外键,

这是繁琐的!

所以我们就使用contenttypes 应用中提供的特殊字段GenericForeignKey,我们可以解决上面的问题:

只需要以下三步:

  • 在model中定义ForeignKey字段,并关联到ContentType表。通常这个字段命名为“content_type”
  • 在model中定义PositiveIntegerField字段,用来存储关联表中的主键。通常这个字段命名为“object_id”
  • 在model中定义GenericForeignKey字段,传入上述两个字段的名字。

具体实例代码:

class Coupon(models.Model):
name = models.CharField(max_length=32) content_type = models.ForeignKey(to=ContentType) # step 1
object_id = models.PositiveIntegerField() # step 2
content_object = GenericForeignKey('content_type', 'object_id') # step 3 def __str__(self):
return self.name

这样的话不管表的数据都可以查询出来,而且添加新的商品的商品,也不需要动优惠券的源码。

但我们在查询的过程中,用ORM实在太繁琐了,所以还有一个反向查询的方法:

就是在每个商品中关联 绑定一个关系:

coupons = GenericRelation(to='Coupon')  # 用于反向查询,不会生成表字段

这样我们就可以直接ORM的.coupons找相应的字段!

Django contenttypes 框架详解的更多相关文章

  1. Django入门基础详解

    本次使用django版本2.1.2 安装django 安装最新版本 pip install django 安装指定版本 pip install django==1.10.1 查看本机django版本 ...

  2. 第五篇Django URL name 详解

    Django URL name 详解 利用Django开发网站,可以设计出非常优美的url规则,如果url的匹配规则(包含正则表达式)组织得比较好,view的结构就会比较清晰,比较容易维护. Djan ...

  3. jQuery Validate验证框架详解

    转自:http://www.cnblogs.com/linjiqin/p/3431835.html jQuery校验官网地址:http://bassistance.de/jquery-plugins/ ...

  4. mina框架详解

     转:http://blog.csdn.net/w13770269691/article/details/8614584 mina框架详解 分类: web2013-02-26 17:13 12651人 ...

  5. lombok+slf4j+logback SLF4J和Logback日志框架详解

    maven 包依赖 <dependency> <groupId>org.projectlombok</groupId> <artifactId>lomb ...

  6. [Cocoa]深入浅出 Cocoa 之 Core Data(1)- 框架详解

    Core data 是 Cocoa 中处理数据,绑定数据的关键特性,其重要性不言而喻,但也比较复杂.Core Data 相关的类比较多,初学者往往不太容易弄懂.计划用三个教程来讲解这一部分: 框架详解 ...

  7. iOS 开发之照片框架详解(2)

    一. 概况 本文接着 iOS 开发之照片框架详解,侧重介绍在前文中简单介绍过的 PhotoKit 及其与 ALAssetLibrary 的差异,以及如何基于 PhotoKit 与 AlAssetLib ...

  8. Quartz.NET作业调度框架详解

    Quartz.NET作业调度框架详解 http://www.cnblogs.com/lmule/archive/2010/08/28/1811042.html

  9. mapreduce框架详解

    hadoop 学习笔记:mapreduce框架详解 开始聊mapreduce,mapreduce是hadoop的计算框架,我学hadoop是从hive开始入手,再到hdfs,当我学习hdfs时候,就感 ...

随机推荐

  1. 《Applying Deep Learning to Answer Selection: A Study And an Open Task》文章理解小结

    本篇论文是2015年的IBM watson团队的. 论文地址: 这是一篇关于QA问题的一篇论文: 相关论文讲解1.https://www.jianshu.com/p/48024e9f7bb22.htt ...

  2. 【Python学习笔记】Coursera课程《Python Data Structures》 密歇根大学 Charles Severance——Week6 Tuple课堂笔记

    Coursera课程<Python Data Structures> 密歇根大学 Charles Severance Week6 Tuple 10 Tuples 10.1 Tuples A ...

  3. Linux下基本栈溢出攻击【转】

    转自:http://blog.csdn.net/wangxiaolong_china/article/details/6844415 版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[ ...

  4. Makefile parameters pass 參數傳遞

    command $make ARCH=7777777777777777777777777777777 Makefile content $(warning $(ARCH)) output Makefi ...

  5. 用tkinter实现的gui小工具

    import tkinter import requests import json from tkinter import * class FindLocation(object): def __i ...

  6. 简单的自动化运维工具(shell+except+whiptail+功能模块化函数+循环)

    简单的自动化运维工具(shell+except+whiptail+功能模块化函数+循环) http://www.cnblogs.com/M18-BlankBox/p/5881700.html

  7. JSON对象与字符串之间的相互转换

    <html> <head> <meta name="viewport" content="width=device-width" ...

  8. CNN中千奇百怪的卷积方式大汇总

    1.原始版本 最早的卷积方式还没有任何骚套路,那就也没什么好说的了. 见下图,原始的conv操作可以看做一个2D版本的无隐层神经网络. 附上一个卷积详细流程: [TensorFlow]tf.nn.co ...

  9. leetcode 之Rotate Image(8)

    这题需要搞清楚矩阵元素的位置关系,尤其是副对角线元素,沿着副对角线元素 void rotateImage(vector<vector<int>> &matrix) { ...

  10. php的设计模式

    1.单一职责原则 单一职责原则(Single Responsibility Principle) 含义:1.避免相同的职责分散到不同的类中,2.避免一个类承担太多的职责: srp的好处: 减少类之间的 ...