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
寫這篇文章的目的是爲了幫助那些採坑的童鞋們再踩到這個坑的時候,能在網上搜到這篇文章,解決你的問題,並對本身解決這個問題作一個記錄,但願可以幫助到你。對象