Django之ContentType详解

  • 一:什么是ContentType
  • 二:应用场景
  • 三:contenttypes 应用
    • 3.1 创建contenttype表
    • 3.2 创建记录和查询
    • 3.3 创建记录
    • 3.4 查询记录

一:什么是ContentType

contenttypes 是Django内置的一个应用,可以追踪项目中所有app和model的对应关系,并记录在ContentType表中。
models.py文件的表结构写好后,通过makemigrations和migrate两条命令迁移数据后,在数据库中会自动生成一个django_content_type表:

每当我们创建了新的model并执行数据库迁移后,ContentType表中就会自动新增一条记录。比如我在应用api的models.py中创建表class Electrics(models.Model): pass。从数据库查看ContentType表,显示如下:

二:应用场景

那么这个表有什么作用呢?这里提供一个场景,网上商城购物时,会有各种各样的优惠券,比如通用优惠券,满减券,或者是仅限特定品类的优惠券。在数据库中,可以通过外键将优惠券和不同品类的商品表关联起来:

from django.db import modelsclass Electrics(models.Model):"""id    name1   日立冰箱2   三星电视3   小天鹅洗衣机"""name = models.CharField(max_length=32)class Foods(models.Model):"""id   name1    面包2    烤鸭"""name = models.CharField(max_length=32)class Clothes(models.Model):name = models.CharField(max_length=32)class Coupon(models.Model):  # 特殊关系表
""" id    name    electric_id   food_id   cloth_id   more...   # 每增加一张表,关系表的结构就要多加一个字段。1   通用优惠券   null       null      null 2   冰箱满减券   2         null     null 3   面包狂欢节   null        1      null
""" name = models.CharField(max_length=32) electric = models.ForeignKey(to='Electrics', null=True) food = models.ForeignKey(to='Foods', null=True) cloth = models.ForeignKey(to='Clothes', null=True)

如果是通用优惠券,那么所有的ForeignKey为null,如果仅限某些商品,那么对应商品ForeignKey记录该商品的id,不相关的记录为null。但是这样做是有问题的:实际中商品品类繁多,而且很可能还会持续增加,那么优惠券表中的外键将越来越多,但是每条记录仅使用其中的一个或某几个外键字段。

三:contenttypes 应用

通过使用contenttypes 应用中提供的特殊字段GenericForeignKey,我们可以很好的解决这个问题。只需要以下三步:
在model中定义ForeignKey字段,并关联到ContentType表。通常这个字段命名为“content_type”
在model中定义PositiveIntegerField字段,用来存储关联表中的主键。通常这个字段命名为“object_id”
在model中定义GenericForeignKey字段,传入上述两个字段的名字。
为了更方便查询商品的优惠券,我们还可以在商品类中通过GenericRelation字段定义反向关系。

3.1 创建contenttype表

from django.db import models
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelationclass Electrics(models.Model):name = models.CharField(max_length=32)price = models.IntegerField(default=100)coupons = GenericRelation(to='Coupon')  # 用于反向查询,不会生成表字段def __str__(self):return self.nameclass Foods(models.Model):name = models.CharField(max_length=32)price=models.IntegerField(default=100)coupons = GenericRelation(to='Coupon')def __str__(self):return self.nameclass Clothes(models.Model):name = models.CharField(max_length=32)price = models.IntegerField(default=100)coupons = GenericRelation(to='Coupon')def __str__(self):return self.nameclass bed(models.Model):name = models.CharField(max_length=32)price = models.IntegerField(default=100)coupons = GenericRelation(to='Coupon')class Coupon(models.Model):"""id    name                      content_type_id       object_id_id1    美的满减优惠券             9(电器表electrics)    32     猪蹄买一送一优惠券         10                     23     南极被子买200减50优惠券    11                     1"""name = models.CharField(max_length=32)content_type = models.ForeignKey(to=ContentType) # step 1object_id = models.PositiveIntegerField() # step 2content_object = GenericForeignKey('content_type', 'object_id') # step 3   不会生成字段,只用于关联到对象上def __str__(self):return self.name

注意:ContentType只运用于1对多的关系!!!并且多的那张表中有多个ForeignKey字段

3.2 创建记录和查询

from django.shortcuts import render, HttpResponse
from api import models
from django.contrib.contenttypes.models import ContentTypedef test(request):if request.method == 'GET':# ContentType表对象有model_class() 方法,取到对应modelcontent = ContentType.objects.filter(app_label='api', model='electrics').first()  # 表名小写cloth_class = content.model_class() # cloth_class 就相当于models.Electricsres = cloth_class.objects.all()print(res)# 为三星电视(id=2)创建一条优惠记录s_tv = models.Electrics.objects.filter(id=2).first()models.Coupon.objects.create(name='电视优惠券', content_object=s_tv)# 查询优惠券(id=1)绑定了哪个商品coupon_obj = models.Coupon.objects.filter(id=1).first()prod = coupon_obj.content_objectprint(prod)# 查询三星电视(id=2)的所有优惠券res = s_tv.coupons.all()print(res)# 查询obj的所有优惠券:如果没有定义反向查询字段,通过如下方式:content = ContentType.objects.filter(app_label='api', model='model_name').first()res = models.OftenAskedQuestion.objects.filter(content_type=content, object_id=obj.pk).all()return HttpResponse('....')

总结: 当一张表和多个表FK关联,并且多个FK中只能选择其中一个或其中n个时,可以利用contenttypes app,只需定义三个字段就搞定!

3.3 创建记录

关系表的结构如下图:

用语法给关系表加记录,添加方式1:


接下来用postman来发送请求

然后代金券表数据就添加完成了

添加方式2:

通过postman发送请求结果

3.4 查询记录

查询name="电商1代金券"的代金券信息

Django之ContentType详解相关推荐

  1. Django REST 框架详解 07 | 三大认证与权限六表

    文章目录 一.三大认证 1. 认证组件:校验用户 2. 权限组件:校验用户权限 3. 频率组件:限制视图接口被访问次数 4. 分析源码 二.权限六表 1. RBAC 认证 2. 权限三表 3. 权限五 ...

  2. Content-Type 详解

    Content-Type 详解 Content-Type 常见Content-Type application/x-www-form-urlencoded multipart/form-data ap ...

  3. Django入门基础详解

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

  4. Django MVT模型详解

    MVT模型详解 ORM简介 使用MySql数据库 开发流程 使用数据库生成模型类 Model 定义模型 定义属性 字段类型 字段选项 关系 元选项 示例演示 测试数据 类的属性 管理器Manager ...

  5. Django模板过滤器详解

    Django 模板过滤器也是我们在以后基于 Django 网站开发过程中会经常遇到的,如显示格式的转换.判断处理等.以下是 Django 过滤器列表,希望对为大家的开发带来一些方便. 一.形式:小写 ...

  6. Django Model设计详解

    Django Model 设计 Django Model设计是Django五项基础核心设计之一(Model设计,URL配置,View编写,Template设计,From使用),也是MVC模式中重要的环 ...

  7. Django之ModelForm详解

    前言 这是一个神奇的组件,通过名字我们可以看出来,这个组件的功能就是把model和form组合起来.先来一个简单的例子来看一下这个东西怎么用: 比如我们的数据库中有这样一张学生表,字段有姓名,年龄,爱 ...

  8. 00x: Django models.Model详解

    Models model是对于信息的一种模型封装与定义.它包含了你要存储的必要字段和操作数据的方法.一句话概括就是,每个模型映射了一张数据表. 基本概念: 每个model都是继承于django.db. ...

  9. 使用 Pycharm 创建一个 Django项目(详解)

    文章目录 Django 简介 创建Django的虚拟环境 1.这里我使用的是anaconda navigator创建的,选择environment,点击create. 2.设置环境名称,选择pytho ...

最新文章

  1. SAP与Ariba在数据分析领域的互补共赢
  2. cdn与服务器的关系_掐指算算: 你的CDN多花了几百万?
  3. html中input两个圆括号,如何使用Jquery将光标聚焦在两个括号(括号)之间?
  4. Dotnet 6.0 深度探索(一)
  5. [javaEE] EL表达式调用java方法
  6. iphone/ipod网页开发教程及规则
  7. 区块链生态系统将崩溃、Rust 超越 Go、无服务器成主导,这十大计算机预测将成真?...
  8. 自己构造公共程序(3)--DataGrid小方法
  9. 唐山大地震 昨夜万人首映 尚雯婕演唱《23秒,32年》使观众情绪得以第二次温暖爆发...
  10. python编译安装没有c扩展_python – 为什么我在安装simplejson时得到“C扩展无法编译”?...
  11. w10恢复出厂设置_w10电脑恢复出厂设置 w10电脑恢复出厂设置的方法
  12. Hexo主题next中添加天气插件(心知天气)
  13. 一切照旧... ...
  14. 不能作为c语言常量的是115L,c语言考试选择题
  15. QQ群加入代码在线获取
  16. rplidar连接计算机显示process has died.....解决方法
  17. 华为服务器2288H v3和V5关机不能启动处理
  18. Focal Loss(ICCV2017 best student paper)
  19. Nand Flash引脚(Pin)的说明
  20. 2021年PMP考试考场公布

热门文章

  1. 供水管网监测系统,供水管网压力监测系统
  2. COOKIE与SESSION的真正区别在哪?
  3. 协方差矩阵的计算及意义
  4. 李宁「向上」:不止缺一个FILA
  5. 里程碑|BSV交易总量突破10亿笔
  6. 野三坡生态文明之环保卫生间
  7. OSChina 周末乱弹 —— 小明滚粗去!源创会走起~
  8. Android UCV 同时打开多路摄像头
  9. Linux之常用基础指令二
  10. 零基础想学编程,应该学习哪一门语言呢?看看各种语言的简介!