问题分析

在之前的一个商城的项目中使用了mysql, 提到mysql就是外键, 多对多等等一系列的表关系

因为是一个商城的项目, 这里面有优惠券, 商品有很多的分类, 不同的商品又有不同的优惠券

其实要说的也就是商品和优惠券的关系,

说到关系那肯定就是用外键, 优惠券外键商品, 但是有一个问题, 一个外键只能指向一张表

现在假如有10个商品表, 一张优惠券表, 要想在一张表中给另外10张表创建外键关系, 那就需要10个外键关系, 10个外键字段

可想而知, 这种方法是不可行的

其实有一种办法那就是, 在优惠券表不直接关联商品表, 而是搞一个中间表, 关联这个中间表, 那这个中间表应该张什么样子呢?

这张表中存储是的app名字和表的名字

id            app_name        model_name
1 mian Human_insurance
2 main Life_insurance

然后优惠券表就这张表建立外键关系, 然后在优惠券中在存储一个object_id, 通过外键找到关联的表, 通过object_id找到表中的对象, 这样就OK了

上面的正常人的想法, django的开发者也是正常人, 哈哈, 他们也想到了, 所以django提供了这样的一张表.

使用ContentType处理外键关系

下面是我写的一个小demo, 这里面就利用了django提供的ContentType来处理外键关系

模型表

from django.db import models
from django.contrib.contenttypes.fields import GenericRelation, GenericForeignKey
from django.contrib.contenttypes.models import ContentType class Book(models.Model):
title = models.CharField(max_length=32)
price = models.FloatField()
category_choices = (("chinese", "中文"), ("english", "英文"), ("development", "开发"), ("network", "网络"))
category = models.CharField(choices=category_choices, max_length=32)
pub_date = models.DateTimeField(null=True, blank=True) content_type = models.ForeignKey(ContentType, blank=True, null=True, on_delete=models.CASCADE)
# 定位对象的id
object_id = models.PositiveIntegerField(blank=True, null=True)
# 定位对象
content_object = GenericForeignKey('content_type', 'object_id') def __str__(self):
return self.title class Publish(models.Model):
name = models.CharField(max_length=32)
address = models.CharField(max_length=128)
books = GenericRelation("Book") def __str__(self):
return self.name

book表中的字段介绍

content_type: 是一个外键字段, 关联的表就是和上面自己构造的表结构一致, 只不过是Django提供的

这样就方便了很多.

object_id: 这个字段存储的就是某张表中的某个对象的id, 所以就是用数字类型进行存储

content_object: 这个字段是一个GenericForeignKey, 这个字段给我们提供了很大的方便, 但是这个字段不会真实的在数据库中创建,

为什么说提供了很大的方便呢?

因为, 在创建book对象的时候可以给content_object传一个对象, 这个字段能够自动找到这个对象的app_name和model_name, 并且填充到content_type和object_id中

这样就不用我们自己去查了

下面就使用这个字段对数据库进行操作

查看书籍的出版社

a = models.Book.objects.filter(id=5).first()
print(a.content_object)
#content_object通过content_type和object_id定位到对象

创建book

创建book的时候需要关联出版社, 这就用道了contentType, 只传一个content_object参数就可以了

# 先查询出出版社
b = models.Publish.objects.filter(id=3).first()
# 创建book
c = models.Book.objects.create(title="test", price=99.9, category="english", content_object=b)
print(c)

修改book的出版社

e = models.Book.objects.filter(title="test").first()
e.content_object = models.Publish.objects.filter(id=4).first()
e.save()

删除

因为我使用的的django2.0, 在创建外键的时候必须指定参数on_delete=models.CASCADE, 将出版社删除了book也就没了

models.Publish.objects.filter(id=1).delete()

总结

使用ContentType来处理大量的外键关系

使用ContentType处理大量的外键关系的更多相关文章

  1. Django——ContentType(与多个表建立外键关系)及ContentType-signals的使用

    一.ContentType 在django中,有一个记录了项目中所有model元数据的表,就是ContentType,表中一条记录对应着一个存在的model,所以可以通过一个ContentType表的 ...

  2. MySQL外键与外键关系说明(简单易懂)

    MySQL主键和外键使用及说明 一.外键约束 MySQL通过外键约束来保证表与表之间的数据的完整性和准确性. 外键的使用条件:  1.两个表必须是InnoDB表,MyISAM表暂时不支持外键(据说以后 ...

  3. Entity Framework Code First主外键关系映射约定

    本篇随笔目录: 1.外键列名默认约定 2.一对多关系 3.一对一关系 4.多对多关系 5.一对多自反关系 6.多对多自反关系 在关系数据库中,不同表之间往往不是全部都单独存在,而是相互存在关联的.两个 ...

  4. 多重外键关系在java中的处理方案

    // 0){ var ul = li.getElementsByTagName("ul")[0]; ul.style.display = "none"; var ...

  5. 通过SQL脚本来查询SQLServer 中主外键关系

    在SQLServer中主外键是什么,以及主外键如何创建,在这里就不说了,不懂的可以点击这里,这篇文章也是博客园的博友写的,我觉得总结的很好: 此篇文章主要介绍通过SQL脚本来查看Sqlserver中主 ...

  6. SQL Server数据库中导入导出数据及结构时主外键关系的处理

    2015-01-26 软件开发中,经常涉及到不同数据库(包括不同产品的不同版本)之间的数据结构与数据的导入导出.处理过程中会遇到很多问题,尤为突出重要的一个问题就是主从表之间,从表有外检约束,从而导致 ...

  7. mysql中主外键关系

    一.外键: 1.什么是外键 2.外键语法 3.外键的条件 4.添加外键 5.删除外键 1.什么是外键: 主键:是唯一标识一条记录,不能有重复的,不允许为空,用来保证数据完整性 外键:是另一表的主键, ...

  8. 【转】PowerDesigner删除外键关系,而不删除外键列

    原文:https://blog.csdn.net/tomsyc/article/details/6075530 PowerDesigner中配置外键关系时,如果要删除配置的外键关系,默认设置会一同删除 ...

  9. MySQL创建数据表并建立主外键关系

    为mysql数据表建立主外键需要注意以下几点: 需要建立主外键关系的两个表的存储引擎必须是InnoDB. 外键列和参照列必须具有相似的数据类型,即可以隐式转换的数据类型. 外键列和参照列必须创建索引, ...

随机推荐

  1. 天诛进阶之D算法 #3700

    http://mp.weixin.qq.com/s/ngn98BxAOLxXPlLU8sWH_g 天诛进阶之D算法 #3700 2015-11-24 yevon_ou 水库论坛 天诛进阶之D算法 #3 ...

  2. SQL Server ->> 深入探讨SQL Server 2016新特性之 --- Row-Level Security(行级别安全控制)

    SQL Server 2016 CPT3中包含了一个新特性叫Row Level Security(RLS),允许数据库管理员根据业务需要依据客户端执行脚本的一些特性控制客户端能够访问的数据行,比如,我 ...

  3. 【源码分析】cocostudio场景编辑器的触发器逻辑

    去看场景编辑器的差不多都可以看到有模拟器的设置(菜单栏的设置).默认是选择cocostudio安装路径中的Simulator.exe这个模拟器,看官网介绍是自己可以选择模拟器,而且公开源代码可以按需设 ...

  4. window搭建svn服务器,本地提交至服务器后,直接同步

    找到版本库目录(在安装svnserver时指定的目录),如下图指定了一个版本库的hooks 在其中创建post-commit.bat文件(可先创建post-cmmit.txt再修改后缀名为bat). ...

  5. windows时间同步脚本

    #!/usr/bin/env python# -*- coding:UTF-8 -*-# 脚本用于windows时间同步,设置window计划任务每五分钟执行一次 import timeimport ...

  6. 【深入理解JAVA虚拟机】第二部分.内存自动管理机制.1.内存区域

    1.内存区域 根据<Java虚拟机规范(Java SE 7版)> 的规定,Java虚拟机所管理的内存将会包括以下几个运行时数据区域,如图所示.  程序计数器 当前线程所执行的字节码的行号指 ...

  7. July 03rd 2017 Week 27th Monday

    Even if you are on the right track, you will get run over if you just sit there. 即使你处于正确的轨道上,但如果你只是坐 ...

  8. hdu-3388 Coprime---容斥定理&&DFS版

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3388 题目大意: 求同时与m,n互质的第k个数是多少! 解题思路: 和HDU-4135类似,将m和n ...

  9. python date,datetime 和time的区别

    这是三个不同类型的数据,例如 2015-11-21 10:51:20: date是日期,表示的是 2015-11-21: datetime是日期时间,表示的是 2015-11-21 10:51:20: ...

  10. HDU 5724 Chess(SG函数)

    Chess Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submi ...