1. 事情原由
今天在写代码的时候,在django 的models目录中新增了一个pkg.py文件,里面定义了一个class, 在执行 makemigrations 的时候,发现这张表始终没法被识别,去网上找了找资料,没有找到这方面的问题的答案。。。app
2. 排查通过
- 尝试把这个class放到models目录中的其余文件中,能够识别到这张表,由此怀疑多是我新加的文件名称的缘由,遂把pkg换成其余名字后,发现仍是没法识别,尝试失败。。。
- 本着搞明白为何会出现这种问题的心理,尝试去读makemigrations的源码,发现里面有个apps对象,保存着全部django app的信息,apps对象中有一个app_config对象,里面放的是AppConfig实例字典,后来读AppConfig源码时发现models_module和models对象嫌疑比较大,经过调试得知models_module对象只是存放了APP的models模块对象,可是models对象始终找不到是从哪里初始化的
- 接着扫描Apps对象的源码,发现了一个可疑的方法,get_registered_model,怀疑class的识别和这个方法应该有关系。在django源码里面全局搜索哪里调用了这个方法,发现了猫腻。这个方法在django源码里面只有在models.base.ModelBase类里面出现过,而且是在__new__方法里面调用。ModelBase类是models.Model的metaclass,因而想明白了整个过程。
- models里面的class都是继承自models.Model,在把这个类装载到内存中的时候,就会触发ModelBase中的new方法,也就是会自动把咱们定义的class注册到AppConfig对象中,如今是没有注册进去,则说明咱们定义的class没有被加载到内存中,在看源码的过程当中发现AppConfig实例化的时候,会初始化models_module,这个操做会将APP中的models目录import到内存中,因而找到了解决办法,在咱们的APP的models目录中的
__init__.py
文件中添加一行 from . import pkg
,在初始化models_module的时候,导入了models目录的同时,会去执行__init__.py
,而执行import的时候,会执行pkg.py文件,也就是把class加载到内存中,实现注册了。
3. 总结
前面的逻辑很绕,我也看了两个小时才把关系大体屡清楚,结论就是若是models目录中定义的py文件中的class类没法在makemigrations的时候被识别到,解决办法就是在models目录的__init__.py
文件中import这个文件,就能识别到这个class类。调试
总的来讲此次看源码大体的解决了面临的问题,可是至今没法找到为何只有我新加的pkg.py文件未加载到内存中,被识别到并注册的缘由。。。django的源码太复杂太绕了。code
写这篇文章的目的是为了帮助那些采坑的童鞋们再踩到这个坑的时候,能在网上搜到这篇文章,解决你的问题,并对本身解决这个问题作一个记录,但愿可以帮助到你。对象