Django contenttypes 应用

什么是Django ContentTypes?

Django ContentTypes是由Django框架提供的一个核心功能,它对当前项目中所有基于Django驱动的model提供了更高层次的抽象接口。

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

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

id app_label model
admin, auth等内置应用…
5 contenttypes contenttype
6 app01 electrics

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

  1. from django.db import models
  2. class Electrics(models.Model):
  3. """
  4. id name
  5. 1 日立冰箱
  6. 2 三星电视
  7. 3 小天鹅洗衣机
  8. """
  9. name = models.CharField(max_length=32)
  10. class Foods(models.Model):
  11. """
  12. id name
  13. 1 面包
  14. 2 烤鸭
  15. """
  16. name = models.CharField(max_length=32)
  17. class Clothes(models.Model):
  18. name = models.CharField(max_length=32)
  19. class Coupon(models.Model):
  20. """
  21. id name Electrics Foods Clothes more...
  22. 1 通用优惠券 null null null
  23. 2 冰箱满减券 2 null null
  24. 3 面包狂欢节 null 1 null
  25. """
  26. name = models.CharField(max_length=32)
  27. electric_obj = models.ForeignKey(to='Electrics', null=True)
  28. food_obj = models.ForeignKey(to='Foods', null=True)
  29. cloth_obj = models.ForeignKey(to='Clothes', null=True)

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

通过使用contenttypes 应用中提供的特殊字段GenericForeignKey,我们可以很好的解决这个问题。只需要以下三步:

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

为了更方便查询商品的优惠券,我们还可以在商品类中通过GenericRelation字段定义反向关系。

示例代码:

  1. from django.db import models
  2. from django.contrib.contenttypes.models import ContentType
  3. from django.contrib.contenttypes.fields import GenericForeignKey
  4. class Electrics(models.Model):
  5. name = models.CharField(max_length=32)
  6. coupons = GenericRelation(to='Coupon') # 用于反向查询,不会生成表字段
  7. def __str__(self):
  8. return self.name
  9. class Foods(models.Model):
  10. name = models.CharField(max_length=32)
  11. coupons = GenericRelation(to='Coupon')
  12. def __str__(self):
  13. return self.name
  14. class Clothes(models.Model):
  15. name = models.CharField(max_length=32)
  16. coupons = GenericRelation(to='Coupon')
  17. def __str__(self):
  18. return self.name
  19. class Coupon(models.Model):
  20. name = models.CharField(max_length=32)
  21. content_type = models.ForeignKey(to=ContentType) # step 1
  22. object_id = models.PositiveIntegerField() # step 2
  23. content_object = GenericForeignKey('content_type', 'object_id') # step 3
  24. def __str__(self):
  25. return self.name

创建记录和查询

  1. from django.shortcuts import render, HttpResponse
  2. from app01 import models
  3. from django.contrib.contenttypes.models import ContentType
  4. def test(request):
  5. if request.method == 'GET':
  6. # ContentType表对象有model_class() 方法,取到对应model
  7. content = ContentType.objects.filter(app_label='app01', model='electrics').first() # 表名小写
  8. cloth_class = content.model_class() # cloth_class 就相当于models.Electrics
  9. res = cloth_class.objects.all()
  10. print(res)
  11. # 为三星电视(id=2)创建一条优惠记录
  12. s_tv = models.Electrics.objects.filter(id=2).first()
  13. models.Coupon.objects.create(name='电视优惠券', content_object=s_tv)
  14. # 查询优惠券(id=1)绑定了哪些商品
  15. coupon_obj = models.Coupon.objects.filter(id=1).first()
  16. prod = coupon_obj.content_object
  17. print(prod)
  18. # 查询三星电视(id=2)的所有优惠券
  19. res = s_tv.coupons.all()
  20. print(res)
  21. # 查询obj的所有优惠券:如果没有定义反向查询字段,通过如下方式:
  22. content = ContentType.objects.filter(app_label='app01', model='model_name').first()
  23. res = models.OftenAskedQuestion.objects.filter(content_type=content, object_id=obj.pk).all()
  24. return HttpResponse('....')

总结:

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

 


Django contenttypes 应用的更多相关文章

  1. 路飞学城知识点4之Django contenttypes 应用

    Django contenttypes 应用 contenttypes 是Django内置的一个应用,可以追踪项目中所有app和model的对应关系,并记录在ContentType表中. 每当我们创建 ...

  2. Django contenttypes 框架详解

    一.什么是Django ContentTypes? Django ContentTypes是由Django框架提供的一个核心功能,它对当前项目中所有基于Django驱动的model提供了更高层次的抽象 ...

  3. Django ContentTypes框架使用场景

    Django contenttypes是一个非常有用的框架,主要用来创建模型间的通用关系(generic relation).不过由于其非常抽象, 理解起来并不容易.当你创建一个django项目的时候 ...

  4. Django contenttypes 组件

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

  5. Django contenttypes组件

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

  6. 20,Django contenttypes 应用

    contenttypes 是Django内置的一个应用,可以追踪项目中所有app和model的对应关系,并记录在ContentType表中. 1.创建一个项目 2.数据库迁移,生成默认表. 3.存着所 ...

  7. Django之contenttypes的应用

    Django contenttypes 应用 简介 contenttypes 是Django内置的一个应用,可以追踪项目中所有app和model的对应关系,并记录在ContentType表中. 每当我 ...

  8. django内置 Contenttypes 框架

    一.什么是Django ContentTypes? 1.Django 包含一个ContentTypes 应用,它可以追踪安装在你的Django 项目里的所有应用,并提供一个高层次的.通用的接口用于与你 ...

  9. django内置组件——ContentTypes

    一.什么是Django ContentTypes? Django ContentTypes是由Django框架提供的一个核心功能,它对当前项目中所有基于Django驱动的model提供了更高层次的抽象 ...

随机推荐

  1. Java面向对象 第4节 类的多态性

    一.多态的概念 在面向对象语言中,多态是指在一棵继承树中的类中可以有多个同名但不同方法体及不同形参的方法.通常有两种途径实现多态:方法的重载和覆盖. 多态性允许以统一的风格处理已存在的变量及相关的类. ...

  2. Docker常用命令(四)

    通过一些例子来了解基本的命令使用   1.查看docker信息       docker info         2.安装完Docker后,里面还有任何镜像,先从仓库下载一个基础镜像,然后在这个基础 ...

  3. java中的内部类详解

    https://www.cnblogs.com/dolphin0520/p/3811445.html https://www.cnblogs.com/chenssy/p/3388487.html

  4. 右击菜单一键优化(增加新建office2003、新建reg和bat,删除新建公文包、新建wps、新建rar)

    右击菜单一键优化(增加新建office2003.新建reg和bat,删除新建公文包.新建wps.新建rar) Windows Registry Editor Version 5.00 [HKEY_CL ...

  5. maven仓库配置阿里云镜像

    maven仓库的默认镜像为国外镜像,下载jar包依赖非常慢,可以将镜像设置为国内的阿里云. 只需要在maven的conf的setting中配置如下: <mirrors> <mirro ...

  6. 学习 MeteoInfo二次开发教程(四)

    教程四的问题不大. 1.private void AddMapFrame_ChinaSouthSea().private void AddTitle()两个函数和public Form1()函数并列. ...

  7. shell脚本四-三剑客

    Shell编程——三剑客 简介 Grep:默认不支持扩展表达式,加-E或者egrep Awk:支持所有zhengze Sed默认不支持扩展表达式,加-r 2.sed语法格式 Sed 选项 命令 文件( ...

  8. Sqlserver 2016 R Service环境安装的各种错误(坑)解决办法

    相信很多朋友都会慕名Sqlserver 2016的R语言功能,将自己的数据库升级到Sqlserver 2016,但是当你安装完Sqlserver 2016的R语言组件之后,你会发现并不能直接使用,比如 ...

  9. 《算法导论》——随机化快排RandomizedQuickSort

    今日算法:随机化快排RandomizedQuickSort 基础工作swap交换和partition分治 /* *交换数组的两个元素 *fromIndex和toIndex为要交换的两个元素的索引 */ ...

  10. python调用cmd显示中文乱码及调用cmd命令

    os.system('dir') 解决方法加上 os.system('chcp 65001') ____________________________________________________ ...