之前用过 StarUML 生成 python 代码, 但是都是利用 class 生成简单的类, 刚好手头有个django 项目, 就试了一下 用 StarMUL 生成model.看效果怎么样.说干就干.
动手之后才发现,这里很多的坑,不建议使用. 首先生成关系不完全, 其次在使用到 同一个表皮多个字段 跟另外一个表同时发生外键/manytomany关系的时候会产生错误, ForeignKey 直接拼写错误....生成文件不遵循 python 编码规范等等等. 用下来虽然比手工撸代码快一点, 但是要认真检查...坑!Q@QQQQ
首先找到 StarUML 插件, 在 StarUML 插件中心中搜索 django. 安装失败....
找到 github https://github.com/josemlp91/staruml-django 安装没有问题...但是文档写的有点坑..后面会讲到
先下载这个Basic Class: https://raw.githubusercontent.com/josemlp91/staruml-django/master/assets/basictypes.mdj
这个是Django 基础类的库文件, 建议不懂的童鞋不要修改, 下载完之后使用这个作为模板使用 starUML 打开,
这个类包含了 Django 的:
Basic Types
string: models.CharField
text: models.TextField
integer: models.IntegerField
decimal: models.DecimalField
boolean: models.BooleanField
date: models.DateField
datetime: models.DateTimeField
email: models.EmailField
file: models.FileField
数据类型, StarUML Django 代码生成器的安装请按照 github 步骤.没有什么问题.
下面讲问题:
它这个 Demo 鬼图,是个例子,但是其他说明一概没有,怎么用都不知道, 根本就是只能自己可以看懂!怎么办呢? 老办法看源代码吧...算了,我还是先说说怎么用吧, 不少童鞋等着看呢, 想自己探究的自己翻看源代码吧..
他这个库共支持三种关系 ForignKey/ManyToMany/OneToOne. 以下是建立关系的注意点:
-
从哪个 Class 出发连接到另一个 Class 则外键就生成在 出发点的 Class 上. 可以根据下图,在Class 画好之后,选择左下方 Association 点击一下,然后从一个Class 连接到另一个Class, 这应该是 StarUML 的基本功. 由于不方便把我的所有数据库结构上传上来,. 所以选了一部分,请见谅
拿作者 github 上面的案例作分析, 从 Student 连接到 School 之后, 然后双击连线中间部分, 键入 school 这个就是外键(或者 m2m, o2m)的名称,即school = models.ForeingKey('School', on_delete=models.PROTECT)
这一句的school,第二步:双击连线出发的一侧在弹出小窗口的右侧选择*
, 然后双击连接线另外一侧选择1
,然后保存,点击菜单栏 Tools --> Django Models--> Generate Code... 选择保存到的的文件夹,打开代码就可以看到跟作者一样的效果啦.... 怎么做是 ForignKey 怎么做才是 ManyToMany? 我们打开源代码
code-generator.js
可以看到以下代码:
if (asso.end1.reference === elem && asso.end2.navigable === true && asso.end2.multiplicity && asso.end1.multiplicity) {
if (asso.end1.multiplicity == "1" && asso.end2.multiplicity == "1"){
var refObjName = asso.end2.reference.name;
var var_name = asso.name;
codeWriter.writeLine(var_name + " = models.OneToOne('" + refObjName + "'"+ tags_str +")");
}
if (['0..*', '1..*', '*'].includes(asso.end1.multiplicity.trim()) && asso.end2.multiplicity == "1"){
var refObjName = asso.end2.reference.name;
var var_name = asso.name;
codeWriter.writeLine(var_name + " = models.ForeingKey('" + asso.end2.reference.name + "'" + tags_str +", on_delete=models.PROTECT)");
}
if (['0..*', '1..*', '*'].includes(asso.end1.multiplicity.trim()) && ['0..*', '1..*', '*'].includes(asso.end2.multiplicity.trim())){
var refObjName = asso.end2.reference.name;
var var_name = asso.name;
codeWriter.writeLine(var_name + " = models.ManyToMany('" + asso.end2.reference.name + "'"+ tags_str +")");
}
}
很明显,这种关系:
1
--> 1
生成 OneToOne
0..*, 1..*, *
--> 1
生成 ForignKey
0..*, 1..*, *
--> 0..*, 1..*, *
生成ManyToMany
ForginKey 里面又有以下关系:
on_delete=None, # 删除关联表中的数据时,当前表与其关联的field的行为
on_delete=models.CASCADE, # 删除关联数据,与之关联也删除
on_delete=models.DO_NOTHING, # 删除关联数据,什么也不做
on_delete=models.PROTECT, # 删除关联数据,引发错误ProtectedError
on_delete=models.SET_NULL, # 删除关联数据,与之关联的值设置为null(前提FK字段需要设置为可空,一对一同理)
但这里好像实现不完全.
一个表存在多个 ForginKey 等关系, 那就... Association 的线多连几遍就好啦...
Demo 图中 大括号里面的东西就是 Tag, 里面有键值对, 这个是StarUML里面的基础知识,我就不在多讲啦.
所有做完之后点击生成代码就好啦. 你很聪明,其中不懂的细节请留言一起交流. 我感觉这个插件暂时还不完善,issue也只有一个, 项目不活跃,估计比较难存活下去, 但毕竟比手撸代码好一点点, 欢迎js高手 Contribute 项目哦.