@

好,现在我们有这样一个需求,我们的商城里有很多的商品,然而节日要来了,我们要搞活动.

那么,我们就要设计优惠券,优惠券都有什么类型呢?满减的、折扣的、立减的、等等等...

我们对应着活动类型,对某类商品设计优惠卷,比如:

家电是一类商品、食物是一类商品,那么我们就可以设计家电折扣优惠券,以及食物满减优惠券等.

所以,我们一顺手,表结构就出来了:

from django.db import models

is_true = {'null': True, 'blank': True}

# 家用电器表
class Appliance(models.Model):
"""
id name
1 冰箱
2 电视
3 洗衣机
"""
name = models.CharField(max_length=64) # 食品表
class Food(models.Model):
"""
id name
1 面包
2 牛掰
"""
name = models.CharField(max_length=64) # 水果表
class Fruit(models.Model):
"""
id name
1 苹果
2 香蕉
"""
name = models.CharField(max_length=64) # class ... # 优惠卷表
class Coupon(models.Model):
"""
id title appliance_id food_id fruit_id
1 通用优惠卷 null null null
2 冰箱折扣券 1 null null
3 电视折扣券 2 null null
4 苹果满减卷 null null 1
"""
title = models.CharField(max_length=64)
appliance = models.ForeignKey(to='Appliance', **is_true)
food = models.ForeignKey(to='Food', **is_true)
fruit = models.ForeignKey(to='Fruit', **is_true)
# ...
# 实际上我们的商品种类会特别多,导致我们这张表的外键也越来越多

殊不知,我们的大Django早就为我们提供了更高明的用法——ContentType组件.


理解

ContentType是Django中内置的一个应用,可以追踪项目中所有的APPmodel的对应关系,并记录在ContentType表中.

当我们的项目做数据迁移后,会在数据库中生成一些Django自带的表,其中就包含django_content_type表.

我们先来看看这张表:



再来看看这张表内默认的数据:



可见,自动就建立了所有APP与其数据表的对应关系.


表结构

步骤

  1. 在model中定义ForeignKey字段,并关联到ContentType表,通常这个字段命名为content-type.
  2. 在model中定义PositiveIntergerField字段,用来存储步骤一中被外键的表中的主键,通常这个字段命名为object_id.
  3. 在model中定义GenericForeignKey字段,传入上面两个字段的名字.
  4. 为了方便反向查询,可在被外键表中定义GenericRelation字段并指向创建外键的表.

好,根据开篇的表结构示例以及如上的步骤,我们的新表结构又出来了:

from django.db import models
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation # 家用电器表
class Appliance(models.Model):
name = models.CharField(max_length=64)
# 4. 为了方便反向查询,可在被外键表中定义GenericRelation字段并指向创建外键的表
coupons = GenericRelation(to='Coupon') # 食物表
class Food(models.Model):
name = models.CharField(max_length=64) # 水果表
class Fruit(models.Model):
name = models.CharField(max_length=64) # 优惠卷表
class Coupon(models.Model):
title = models.CharField(max_length=64)
# 1. 在model中定义ForeignKey字段,并关联到ContentType表
content_type = models.ForeignKey(to=ContentType) # 这里就不要加引号了
# 2. 在model中定义PositiveIntergerField字段,用来存储步骤一中被外键的表中的主键
object_id = models.PositiveIntegerField()
# 3. 在model中定义GenericForeignKey字段,传入上面两个字段的名字.
content_object = GenericForeignKey('content_type', 'object_id')

数据迁移后,django_content_type表中自动就增加了APP与其model的对应字段.

使用

首先 我们准备些数据

# 在Python脚本中调用Django环境
import os if __name__ == '__main__':
# 注意将下面的'blog097.settings'改为对应的配置文件路径
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'blog097.settings')
import django
django.setup()
from blog import models [models.Appliance.objects.create(name=i) for i in ("冰箱", "电视", "洗衣机")]
[models.Food.objects.create(name=i) for i in ("面包", "牛奶")]
[models.Fruit.objects.create(name=i) for i in ("苹果", "香蕉")]

如果不能理解此操作,可见博文:【在Python脚本中调用Django环境】

然后 开始我们的ORM操作

# 在Python脚本中调用Django环境
import os if __name__ == '__main__':
# 注意将下面的'blog097.settings'改为对应的配置文件路径
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'blog097.settings')
import django
django.setup()
from blog import models
from django.contrib.contenttypes.models import ContentType """通过ContentType获得表名"""
content_type_obj = ContentType.objects.filter(app_label='blog', model='appliance').first() # 打印结果:appliance """获得表内的所有对象,相当于models.Applicance"""
model_class = content_type_obj.model_class() # <class 'blog.models.Appliance'>
obj_list = model_class.objects.all()
[print(obj.name) for obj in obj_list] # 冰箱、电视、洗衣机 """为冰箱添加一条优惠记录"""
ice_box = models.Appliance.objects.filter(name="冰箱").first()
models.Coupon.objects.create(title="冰箱折扣券", content_object=ice_box) """查询冰箱的所有优惠卷"""
# 我们定义了反向查询
coupon_list01 = ice_box.coupons.all()
[print(coupon.title) for coupon in coupon_list01] # 如果没有定义反向查询
coupon_list02 = models.Coupon.objects.filter(content_type=content_type_obj, object_id=ice_box.id).all()
[print(coupon.title) for coupon in coupon_list02]


【Django】ContentType组件的更多相关文章

  1. python 全栈开发,Day98(路飞学城背景,django ContentType组件,表结构讲解)

    昨日内容回顾 1. 为什么要做前后端分离? - 前后端交给不同的人来编写,职责划分明确. - API (IOS,安卓,PC,微信小程序...) - vue.js等框架编写前端时,会比之前写jQuery ...

  2. Django ContentType组件

    ContentType组件 引入 现在我们有这样一个需求~我们的商城里有很多的商品~~节日要来了~我们要搞活动~~ 那么我们就要设计优惠券~~优惠券都有什么类型呢~~满减的~折扣的~立减的~~ 我们对 ...

  3. vue创建路由,axios前后台交互,element-ui配置使用,django contentType组件

    vue中创建路由 每一个vue组件都有三部分组成 template:放html代码 script:放js相关 style:放css相关 vue中创建路由 1.先创建组件 Course.vue 2.ro ...

  4. Django content-type组件

    介绍 Django包含一个contenttypes应用程序(app),可以跟踪Django项目中安装的所有模型(Model),提供用于处理模型的高级通用接口. Contenttypes应用的核心是Co ...

  5. Django之ContentType组件

    一.理想表结构设计 1.初始构建 1. 场景刚过去的双12,很多电商平台都会对他们的商品进行打折促销活动的,那么我们如果要实现这样的一个场景,改如何设计我们的表? 2. 初始表设计 注释很重要,看看吧 ...

  6. Django组件(五) Django之ContentType组件

    基础使用 -contenttype组件 -django提供的一个快速连表操作的组件,可以追踪项目中所有的APP和model的对应关系,并记录在ContentType表中. 当我们的项目做数据迁移后,会 ...

  7. ContentType组件,Django缓存机制,跨域请求

    ContentType组件 解决什么问题:表的id和数据id,来唯一确定一条数据 用: 插入数据: models:content_obj = GenericForeignKey('table_id', ...

  8. contenttype组件、Django缓存机制以及跨域请求

    1 昨日回顾 版本控制 *** (1)url=127.0.0.1/course/?version=v100000 1 versioning_class=QueryParameterVersioning ...

  9. Django day31 contentType组件,Django的缓存

    一.contentType组件 1.干什么用的? 是一个django内置的一个组件,方便我们快速的连表操作 2.这两个字段都不会在数据库中生成,他只是用来查询,插入的 -在course表中: poli ...

随机推荐

  1. 阿里云slb上传证书错误

    阿里云上传证书错误 今天在阿里云给slb上传新买的证书,传的过程中报错了,如下: 网上找了半天没找到,鼠标放在错误哪行行首,会报一个错 大意就是一行最多64个字符,我检查了下,报错这行是68个字符,于 ...

  2. MongoDB 的replicattion 复制集练习

              replicattion 相当于 mysql 的主从复制的读写分离,共同维护相同的数据,提高服务器的可用性[假如主(PRIMARY)不能用时,mongo会迅速自动切到从(SECON ...

  3. Linux学习-Ubuntu 18.04-安装图文教程

    Ubuntu(友帮拓.优般图.乌班图)是一个以桌面应用为主的开源GNU/Linux操作系统,Ubuntu 是基于Debian GNU/Linux,支持x86.amd64(即x64)和ppc架构,由全球 ...

  4. fuser ---显示出当前程序使用磁盘上的某个文件

    fuser 可以显示出当前哪个程序在使用磁盘上的某个文件.挂载点.甚至网络端口,并给出程序进程的详细信息. fuser只把PID输出到标准输出,其他的都输出到标准错误输出. a 显示所有命令行中指定的 ...

  5. 【SRM 717 DIV2 C】DerangementsDiv2

    Problem Statement You are given two ints: n and m. Let D be the number of permutations of the set {1 ...

  6. JVM学习心得

    出处:http://blog.csdn.net/qq_16143915/article/details/51195438 一.JAVA内存管理与GC机制 Java在JVM所虚拟出的内存环境中执行,ja ...

  7. error:assign attribute must be unsafeunretained

    今天在使用协议的过程中.偶然发现这样使用 ? 1 2 3 4 5 6 7 8 9 10 @interface AppDelegate (){     id<chatdelegate>  t ...

  8. Ext4.0 经常使用代码整理(一)

    一:经常使用工具条上的定义 // 工具条 var toolbar = Ext.create("Ext.Toolbar", {             items : [ yearC ...

  9. vue2.0-transition配合animate.css

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  10. BZOJ5106: [CodePlus2017]汀博尔

    [传送门:BZOJ5106] 简要题意: 给出n棵树,初始高度为h[i],每棵树每个月长高a[i] 现有一个客户,需要至少s长的总木材,而且每次截取的木材必须是一整颗树而且高度大于等于L 求出最少的月 ...