一、理想表结构设计

1、初始构建

1. 场景
刚过去的双12,很多电商平台都会对他们的商品进行打折促销活动的,
那么我们如果要实现这样的一个场景,改如何设计我们的表?

2. 初始表设计

  1. 注释很重要,看看吧
  2. from django.db import models
  3.  
  4. # Create your models here.
  5.  
  6. # 食物类
  7. class Food(models.Model):
  8. '''
  9. 理想中的表数据
  10. id title
  11. 1 猪肉
  12. 2 牛肉
  13. '''
  14. title = models.CharField(max_length=32)
  15.  
  16. # 水果类
  17. class Fruit(models.Model):
  18. '''
  19. 理想中的表数据
  20. id title
  21. 1 苹果
  22. 2 榴莲
  23. '''
  24. title = models.CharField(max_length=32)
  25.  
  26. # 双12打折,优惠卷类
  27. class Coupon(models.Model):
  28. '''
  29. 理想中的数据表
  30. id title food_id fruit_id xxx_id ...
  31. 1 猪肉9.9折 1 null
  32. 2 榴莲11折 null 2
  33. 但是这样构建表结构是不现实的,因为如果我的分类有几十种呢,不就要几十个外键吗
  34. ########################################################################
  35. 因此,我们想到了另一种方法,再建一张MyTable表,专门用于存放表,我们的优惠表就可以如下设计
  36. id title table_id object_id
  37. 1 猪肉9.9折 1 1
  38. 2 榴莲11折 2 2
  39.  
  40. table_id找到是哪一张表,object_id是找到那种表的某条数据
  41. '''
  42. title = models.CharField(max_length=32)
  43. # 定位表
  44. table = models.ForeignKey(to='MyTable')
  45. object_id = models.IntegerField()
  46.  
  47. class MyTable(models.Model):
  48. '''
  49. id app_name table_name
  50. 1 Demo food
  51. 2 Demo fruit
  52. 3 Demo coupon
  53. '''
  54. app_name = models.CharField(max_length=32)
  55. table_name = models.CharField(max_length=32)

3. 缺点
这样设计的缺点在于,我每次新建一张表,就必须到MyTable表里面记录,
但是不用担心,我们能想到的,Django也帮我们想到了,
Django的ContentType组件就帮我们实现了跟MyTable一样的表结构,而且你每建一张表,都会自动录进去,不需要自己录入。

二、ContentType

1、介绍

ContentType是Django的内置的一个应用,可以追踪项目中所有的APP和model的对应关系,并记录在ContentType表中。
当我们的项目做数据迁移后,会有很多django自带的表,其中就有django_content_type表。

ContentType组件应用:
  -- 在model中定义ForeignKey字段,并关联到ContentType表,通常这个字段命名为content_type(使用其他命名反向查询会报错)

  -- 在model中定义PositiveIntergerField字段, 用来存储关联表中的主键,通常我们用object_id

  -- 在model中定义GenericForeignKey字段,传入上面两个字段的名字

  -- 方便反向查询可以定义GenericRelation字段

注意:
  -- 也就是说GenericForeignKey是正向查,GenericRelation是反向查
  -- ContentType表中的对象可以使用model_class()这个方法拿到具体的那张表

2、models

  1. from django.db import models
  2. from django.contrib.contenttypes.models import ContentType
  3. from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
  4.  
  5. # Create your models here.
  6.  
  7. class Food(models.Model):
  8. '''
  9. 理想中的表数据
  10. id title
  11. 1 猪肉
  12. 2 牛肉
  13. '''
  14. title = models.CharField(max_length=32)
  15. # 只用于反向查询,也不生成字段
  16. coupons = GenericRelation(to='Coupon')
  17. class Fruit(models.Model):
  18. '''
  19. 理想中的表数据
  20. id title
  21. 1 苹果
  22. 2 榴莲
  23. '''
  24. title = models.CharField(max_length=32)
  25. # 双12打折,有优惠价
  26. class Coupon(models.Model):
  27. '''
  28. 理想中的数据表
  29. id title food_id fruit_id xxx_id ...
  30. 1 猪肉9.9折 1 null
  31. 2 榴莲11折 null 2
  32. 但是这样构建表结构是不现实的,因为如果我的分类有几十种呢,不就要几十个外键吗
  33. ########################################################################
  34. 因此,我们想到了另一种方法,再建一张MyTable表,专门用于存放表,我们的优惠表就可以如下设计
  35. id title table_id object_id
  36. 1 猪肉9.9折 1 1
  37. 2 榴莲11折 2 2
  38.  
  39. table_id找到是哪一张表,object_id是找到那种表的某条数据
  40. '''
  41. title = models.CharField(max_length=32)
  42. # 自己的表
  43. # table = models.ForeignKey(to='MyTable')
  44. # object_id = models.IntegerField()
  45. ########################################################
  46. # Django提供的表
  47. # 1.跟ComtentType表绑定关系
  48. content_type = models.ForeignKey(to=ContentType)
  49. # 2.对象的id
  50. object_id = models.PositiveIntegerField()
  51. #------------------------------------------------------#
  52. # 如果就这样创建表,那么在新建这个表的数据的时候会很麻烦
  53. # 比如:
  54. # table_id = ContentType.objects.filter(app_label='Demo', model='food').first().id
  55. # Coupon.objects.create(title=xxx, content_type_id=table_id, object_id=x)
  56. # 因此Django也给我们提供了方便的用法,通过表id和object_id不就是为了定位到具体的某个对象吗
  57. # 使用content_obj,会直接根据这个对象去帮你找到对应的content_type_id和object_id
  58. # 这样创建表的时候就容易多了:Coupon.object.create(title=xxx, content_obj=obj)
  59. # 注意:content_obj不是字段,不存在数据库中的,只是Django为了给我们提供方便而帮我们做的一些操作
  60. # 3.通过外键关系给表及对象id绑定关系,不生成字段
  61. content_obj = GenericForeignKey('content_type', 'object_id')

3、示例

  1. class TestView(views.View):
  2. def get(self, request):
  3. # 原始方法给猪肉创建优惠卷
  4. # ContentType的字段是app_label和model
  5. content_type_id = ContentType.objects.filter(app_label='Demo', model='food').first().id
  6. object_id = Food.objects.filter(title='猪肉').first().id
  7. Coupon.objects.create(title='猪肉9.9折', content_type_id=content_type_id, object_id=object_id)
  8.  
  9. # 用ContentType给榴莲创建优惠卷
  10. obj = Fruit.objects.filter(title='榴莲').first()
  11. Coupon.objects.create(title='榴莲11折', content_obj=obj)
  12.  
  13. # 原始方法查榴莲的所有优惠卷
  14. content_type = ContentType.objects.filter(app_label='Demo', model='fruit').first()
  15. ret = Coupon.objects.filter(content_type=content_type, object_id=2).all()
  16. print(ret[0].title)
  17.  
  18. # 用Django提供的ContentType的反向查猪肉的优惠卷
  19. ret = Food.objects.filter(title='猪肉').first().coupons.all()
  20. print(ret[0].title)
  21.  
  22. # 正向查,优惠卷id=1绑定了哪个对象
  23. coupon_obj = Coupon.objects.filter(id=1).first()
  24. print(coupon_obj.content_obj.title)
  25.  
  26. # 通过ContentType获得表名
  27. content = ContentType.objects.filter(app_label='Demo', model='fruit').first()
  28. # 获得表model对象 相当于models.Fruit
  29. fruit_model = content.model_class()
  30. fruit_list = fruit_model.objects.all()
  31. for fruit in fruit_list:
  32. print(fruit.title)
  33.  
  34. return HttpResponse('ok')

Django之ContentType组件的更多相关文章

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

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

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

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

  3. 【Django】ContentType组件

    目录 理解 表结构 使用 @ 好,现在我们有这样一个需求,我们的商城里有很多的商品,然而节日要来了,我们要搞活动. 那么,我们就要设计优惠券,优惠券都有什么类型呢?满减的.折扣的.立减的.等等等... ...

  4. Django中content-type组件

    django-content 1.需求 一家餐馆,有多个菜系,粤菜.湘菜.闽南菜.东北菜等,每个菜系中的菜品又分为小份.中份.大份,每个菜系对应的菜品量价格不同,现需要将该需求建表. 2. 建表方式 ...

  5. Django中content-type组件的使用

    content-type组件 ContentType是Django的内置的一个应用,可以追踪项目的所有APP和model的对应关系,并记录在ContentTpe表中,当我们的项目做数据迁移后,会有很多 ...

  6. Django :Content-Type组件

    Content_Type 组件 用法: model.py: from django.db import models # Create your models here. class Food(mod ...

  7. Django 之 ContentType组件

    一.什么是 ContentTypes ContentTypes 是 Django 内置的一个应用,它可以追踪记录项目中所有 app 和 model 的对应关系,并记录在 django_content_ ...

  8. Django:ContentType组件

    一.项目背景 二.版本一 三.版本二 三.终极版(使用ContentType) 一.项目背景 luffy项目,有课程有学位课(不同的课程字段不一样),价格策略 问题:1.如何设计表结构,来表示这种规则 ...

  9. django内置组件——ContentTypes

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

随机推荐

  1. Windows中通过命令行新建文件夹、新建文件,和一些常用命令

    新建文件 和Linux不太一样,Linux中的touch和vi命令创建新文件的方法都不能用了,在windows命令行下得用type nul>文件名.后缀名来创建: F:\study\vue\wo ...

  2. [JS设计模式]:构造函数模式(2)

    基本用法 function Car(model, year, miles) { this.model = model; this.year = year; this.miles = miles; th ...

  3. Git代码管理

    持续更新中...   有道笔记链接:http://note.youdao.com/noteshare?id=10a0a86a3499f92cf26371f2698b97d2   Git网上平台 Git ...

  4. 解决sqlserver数据库显示单个用户

    今天突然发现数据库显示为单个用户并且,访问速度超慢,执行以下语句解决了 USE master; GO DECLARE @SQL VARCHAR(MAX); SET @SQL='' SELECT @SQ ...

  5. SQLServer之创建DML AFTER INSERT触发器

    DML AFTER INSERT触发器创建原理 触发器触发时,系统自动在内存中创建deleted表或inserted表,内存中创建的表只读,不允许修改,触发器执行完成后,自动删除. insert触发器 ...

  6. JavaScript对象类型之简单介绍

    引言 对象是JavaScript的基本数据类型. 对象是一种复合值:将很多值(原始值或者其他对象)聚合在一起,通过名字访问这些值. 对象可以看做属性的无序集合,每个属性都是一个名/值对.属性名是字符串 ...

  7. Springboot项目配置druid数据库连接池,并监控统计功能

    pom.xml配置依赖 <!-- https://mvnrepository.com/artifact/com.alibaba/druid --> <dependency> & ...

  8. Linux下Power Management开发总结

    本文作为一个提纲挈领的介绍性文档,后面会以此展开,逐渐丰富. 1. 前言 在 <开发流程>中介绍了PM开发的一般流程,重点是好的模型.简单有效的接口参数.可量化的测试环境以及可独性强的输出 ...

  9. triplet loss 在深度学习中主要应用在什么地方?有什么明显的优势?

    作者:罗浩.ZJU链接:https://www.zhihu.com/question/62486208/answer/199117070来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转 ...

  10. C# GDI+绘制一维条码打印模糊的解决办法

    最近遇到使用zxing生成的一维条码打印出来的条码图形很模糊根本识别不了.其实原因只有一句话: bitmap没有直接使用PrintDocument的Graphics画布进行绘制,而是中间处理了一下外部 ...