Django从零开始构建CMDB平台之模型设计(一)

一 模型设计

传统设计来讲,是一个资产一个表,那么关系型数据库多少张合适?
可以认为不同型号的产品都是一个资产,那么不同产品放在一张表中肯定不现实,每个场景一张表,那么如果新加场景如何考虑?增加字段?增加多少字段?
所以我们要引入一种方式进行实现这些信息,不同信息是不一样的,比如id信息是一种信息,主机名等也是一种信息,即使分析的再好,一旦广泛使用起来,那么需求也陆续膨胀
这样的设计带来很大的问题:字段无法控制,扩展性不够,大量的字段冗余,看似名字差不多,名字也差不多

设计模型

class CISchema(models.Model):
    name = models.CharField("模型名称", max_length=32, null=False, blank=False, unique=True)
    alias = models.CharField("模型别名", max_length=32, null=False, blank=False)
    desc = models.CharField("描述", max_length=255, default='', null=True, blank=True)
    icon_url = models.CharField("图标", max_length=255, default='', null=True, blank=True)

这里一条数据对应表示一个表,即:
在这里插入图片描述
这代表一个部门表
那么它的字段是存放在哪里呢?

设计模型字段

class CIField(models.Model):
    name = models.CharField("字段名称", max_length=32, null=False, blank=False, unique=True)
    alias = models.CharField("字段别名", max_length=32, default='')
    value_type = models.CharField("值的类型", choices=VALUE_TYPE_MAP, blank=False, null=False, max_length=2)
    meta = models.JSONField("字段属性", default=dict)

value_type 是值得类型

class ValueTypeEnum:
    INT = "0"
    FLOAT = "1"
    TEXT = "2"
    DATETIME = "3"
    DATE = "4"
    TIME = "5"
    JSON = "6"
    CHAR = "7"
    ENUM = "8"


VALUE_TYPE_MAP = (
    (ValueTypeEnum.INT, "整型"),
    (ValueTypeEnum.FLOAT, "浮点型"),
    (ValueTypeEnum.TEXT, "文本型"),
    (ValueTypeEnum.DATETIME, "日期时间"),
    (ValueTypeEnum.DATE, "日期"),
    (ValueTypeEnum.TIME, "时间"),
    (ValueTypeEnum.JSON, "JSON"),
    (ValueTypeEnum.CHAR, "字符串"),
    (ValueTypeEnum.ENUM, "枚举"),
)

meta是元数据,用来限制或验证值得唯一性和必填

  1. CISchema 和CIField的关系考虑是一对多或者多对多
    要求一个字段只能对应某一个明确的表中,即使字段名称一样,但是类型不一样,类型即使一样其他属性也不一样,即使同一个字段,但是所谓的描述信息不一样,有的int 有的bigint 等等
    即使看似像同一字段,可复用的功能性不是很强,但是实现可复用情况一定很高
    所以采取简单化的设计:通过不同表的字段和其他表的字段没有任何关系
    为了简化这样的关系,这里的meta描述是不一样的
    采取一对多关系
class CIField(models.Model):
    name = models.CharField("字段名称", max_length=32, null=False, blank=False, unique=True)
    alias = models.CharField("字段别名", max_length=32, default='')

    value_type = models.CharField("值的类型", choices=VALUE_TYPE_MAP, blank=False, null=False, max_length=2)
    meta = models.JSONField("字段属性", default=dict)
    schema = models.ForeignKey("CISchema", related_name="field", on_delete=models.CASCADE, db_constraint=False,
                               null=False, blank=False, default='')

db_constraint 个就是保留跨表查询的便利(双下划线跨表查询```),但是不用约束字段了,一半公司都用false,这样就省的报错,因为没有了约束(Field字段对象,既约束,又建立表与表之间的关系)

设计value表

有了模型字段,现在设计存储的value值

class CIIntValue(models.Model):
    ALLOW_INDEX = True

    ci = models.ForeignKey("CI", on_delete=models.CASCADE, db_constraint=False)
    field = models.ForeignKey("CIField", on_delete=models.CASCADE, db_constraint=False)
    value = models.IntegerField("整型值", null=False, blank=False)

    class Meta:
        verbose_name = "整型值"

模型字段与值一对多关系 CI表为模型中每一条配置项,下面开始设计CI表
因为value值有多种格式,根据值类型不同建立多个 value类

MODEL_TYPE_MAP = {
    ValueTypeEnum.INT: CIIntValue,
    ValueTypeEnum.FLOAT: CIFloatValue,
    ValueTypeEnum.TEXT: CITextValue,
    ValueTypeEnum.DATETIME: CIDatetimeValue,
    ValueTypeEnum.DATE: CIDateValue,
    ValueTypeEnum.TIME: CITimeValue,
    ValueTypeEnum.JSON: CIJsonValue,
    ValueTypeEnum.CHAR: CICharValue,
    ValueTypeEnum.ENUM: CICharValue,
}

详细代码GitHub

设计ci表

ci 指configuration item

class CI(models.Model):
    schema = models.ForeignKey("CISchema", on_delete=models.CASCADE, related_name="item", db_constraint=False)

与模型关联,增加一个配置项,在ci表中多一条记录

限制值得唯一性或必填性

在CIField表中meta是JsonField格式(Django3.1新增Field,如果Django低于3.1可以安装第三方库来添加(django-mysql))
meta可以定义是否需要验证唯一性或必填,json格式方便扩展。

模型关联关系

class CISchema(models.Model):
    name = models.CharField("模型名称", max_length=32, null=False, blank=False, unique=True)
    alias = models.CharField("模型别名", max_length=32, null=False, blank=False)
    desc = models.CharField("描述", max_length=255, default='', null=True, blank=True)
    icon_url = models.CharField("图标", max_length=255, default='', null=True, blank=True)

    relation = models.ManyToManyField("self", related_name="relation_schema", through="SchemaThroughRelation",
                                      symmetrical=False, through_fields=('parent', 'child'))
class SchemaThroughRelation(models.Model):
    parent = models.ForeignKey("CISchema", related_name="_child", on_delete=models.CASCADE, db_constraint=False)
    child = models.ForeignKey("CISchema", related_name="_parent", on_delete=models.CASCADE, db_constraint=False)
    relation = models.ForeignKey("Relation", related_name="ci_schema", on_delete=models.CASCADE, db_constraint=False)

    class Meta:
        verbose_name = "模型和关系穿梭表"
class Relation(models.Model):
    name = models.CharField("关系名称", max_length=32, null=False, blank=False, unique=True)
    alias = models.CharField("字段别名", max_length=32, default='')

关联关系relation 多对多自我关联,自定义多对多中间表,添加外键关联Relation关系详情。

总结

基本得数据结构已经建立好,接下需要扩展的模型之后章节涉及到再讲。
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值