Django之ContentType详解
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详解相关推荐
- Django REST 框架详解 07 | 三大认证与权限六表
文章目录 一.三大认证 1. 认证组件:校验用户 2. 权限组件:校验用户权限 3. 频率组件:限制视图接口被访问次数 4. 分析源码 二.权限六表 1. RBAC 认证 2. 权限三表 3. 权限五 ...
- Content-Type 详解
Content-Type 详解 Content-Type 常见Content-Type application/x-www-form-urlencoded multipart/form-data ap ...
- Django入门基础详解
本次使用django版本2.1.2 安装django 安装最新版本 pip install django 安装指定版本 pip install django==1.10.1 查看本机django版本 ...
- Django MVT模型详解
MVT模型详解 ORM简介 使用MySql数据库 开发流程 使用数据库生成模型类 Model 定义模型 定义属性 字段类型 字段选项 关系 元选项 示例演示 测试数据 类的属性 管理器Manager ...
- Django模板过滤器详解
Django 模板过滤器也是我们在以后基于 Django 网站开发过程中会经常遇到的,如显示格式的转换.判断处理等.以下是 Django 过滤器列表,希望对为大家的开发带来一些方便. 一.形式:小写 ...
- Django Model设计详解
Django Model 设计 Django Model设计是Django五项基础核心设计之一(Model设计,URL配置,View编写,Template设计,From使用),也是MVC模式中重要的环 ...
- Django之ModelForm详解
前言 这是一个神奇的组件,通过名字我们可以看出来,这个组件的功能就是把model和form组合起来.先来一个简单的例子来看一下这个东西怎么用: 比如我们的数据库中有这样一张学生表,字段有姓名,年龄,爱 ...
- 00x: Django models.Model详解
Models model是对于信息的一种模型封装与定义.它包含了你要存储的必要字段和操作数据的方法.一句话概括就是,每个模型映射了一张数据表. 基本概念: 每个model都是继承于django.db. ...
- 使用 Pycharm 创建一个 Django项目(详解)
文章目录 Django 简介 创建Django的虚拟环境 1.这里我使用的是anaconda navigator创建的,选择environment,点击create. 2.设置环境名称,选择pytho ...
最新文章
- SAP与Ariba在数据分析领域的互补共赢
- cdn与服务器的关系_掐指算算: 你的CDN多花了几百万?
- html中input两个圆括号,如何使用Jquery将光标聚焦在两个括号(括号)之间?
- Dotnet 6.0 深度探索(一)
- [javaEE] EL表达式调用java方法
- iphone/ipod网页开发教程及规则
- 区块链生态系统将崩溃、Rust 超越 Go、无服务器成主导,这十大计算机预测将成真?...
- 自己构造公共程序(3)--DataGrid小方法
- 唐山大地震 昨夜万人首映 尚雯婕演唱《23秒,32年》使观众情绪得以第二次温暖爆发...
- python编译安装没有c扩展_python – 为什么我在安装simplejson时得到“C扩展无法编译”?...
- w10恢复出厂设置_w10电脑恢复出厂设置 w10电脑恢复出厂设置的方法
- Hexo主题next中添加天气插件(心知天气)
- 一切照旧... ...
- 不能作为c语言常量的是115L,c语言考试选择题
- QQ群加入代码在线获取
- rplidar连接计算机显示process has died.....解决方法
- 华为服务器2288H v3和V5关机不能启动处理
- Focal Loss(ICCV2017 best student paper)
- Nand Flash引脚(Pin)的说明
- 2021年PMP考试考场公布