一 模型设计
传统设计来讲,是一个资产一个表,那么关系型数据库多少张合适?
可以认为不同型号的产品都是一个资产,那么不同产品放在一张表中肯定不现实,每个场景一张表,那么如果新加场景如何考虑?增加字段?增加多少字段?
所以我们要引入一种方式进行实现这些信息,不同信息是不一样的,比如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是元数据,用来限制或验证值得唯一性和必填
- 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,
}
设计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关系详情。
总结
基本得数据结构已经建立好,接下需要扩展的模型之后章节涉及到再讲。