天天看点

禁用django的物理外键(CONSTRAINT,REFERENCES)背景第一次尝试第二次尝试后记

背景

用django自带的admin和auth搭建了内部网站,使用了django的用户和权限分组系统,但是在移到生产环境时发现公司把REFERENCES这种命令禁止了,DBA说影响性能不给开权限,所以不得不尝试把外键从db层移到应用层。

第一次尝试

刚开始只找到https://docs.djangoproject.com/en/dev/ref/models/fields/#django.db.models.ForeignKey.db_constraint,中db_constraint这个参数,尝试了下的确可以移除物理外键,但是由于我使用的User,Group等对象都是django内部的模型,我如果要修改的话,要么改源码,要么只能重写了。

于是模仿https://www.zhihu.com/question/61129892/answer/189472143中,对AbstractBaseUser和PermissionsMixin这两个类里只要用到ForeignKey或者manttomany的字段都加上db_constraint=False这个参数。具体代码就不展示了。反正最后不是很顺利,跟内部很多东西有冲突,看起来即使弄好了也没法用权限系统,因此尝试其他方法。

第二次尝试

思路:之后就把目光投向了django本身对于db的全局设置,因为我在看文档时无意中看到关于InnoDB相关的东西,后来通过https://docs.djangoproject.com/en/2.0/ref/databases/#storage-engines得知,只有InnoDB支持物理外键,而MyISAM不支持。也就是说如果我使用MyISAM的话,django可能就不得不把外键放在物理层了。

于是参考文档在setting的DATABASES中default中添加了

'OPTIONS': {
             'init_command': 'SET default_storage_engine=MyISAM',
           },           

这一参数,再次重新生成数据库就发现没有物理外键了。

后记

虽然这样设置了,但是在生产环境db上初始化时还是会出现

django.db.utils.OperationalError: (1142, "REFERENCES command denied to user 'xxx'@'xxxx' for table 'django_content_type'")

的报错,但是把本地的db导出sql语句时并没有REFERENCES命令。于是就直接在本地数据库初始化,之后生成见表语句后导入生产db即可。

ps:最好把本地初始化时的数据和表结构一起导入,不然的话’auth_permission’这个表会是空的,之后用admin界面的话管理员进去也没有权限。

上一篇: FreeWriting_1
下一篇: React 顶层 API