網(wǎng)站首頁 編程語言 正文
一、前言
當(dāng)我們在django中添加或修改了數(shù)據(jù)庫model后,一般需要執(zhí)行makemigrations、migrate把我們的model類生成相應(yīng)的數(shù)據(jù)庫表,或修改對應(yīng)的表結(jié)構(gòu)。這是非常方便的。
但我們在實(shí)際使用中執(zhí)行這兩個命令經(jīng)常會出現(xiàn)意向不到的報錯。下面為你詳細(xì)講解這兩個命令,讓你更從容的使用他們!
二、migrate和makemigrations詳解和實(shí)操
1. makemigrations
makemigrations會把我們寫的model生成數(shù)據(jù)庫遷移文件
比如我們建立一個一個Product的模型
class Product(models.Model): id = models.AutoField(primary_key=True) key = models.CharField(max_length=255) created = models.DateTimeField() suite_id = models.IntegerField(blank=True, null=True) report_version_id = models.IntegerField(null=True) class Meta: db_table = 'client'
然后執(zhí)行命令python manage.py makemigrations
會生成遷移文件(如果沒有生成遷移文件,記得添加【apps.py】文件并配置,再將其app名稱加入INSTALLED_APPS中)
如果我們有多個apps的文件可以指定app名稱進(jìn)行遷移文件的生成,命令
python manage.py makemigrations [app_label]
一般我們使用這個命令就夠了!
當(dāng)然還有其他命令給我們使用比如執(zhí)行
python manage.py makemigrations --dry-run --verbosity 3
生成遷移文件的代碼
可以使用 python manage.py makemigrations --no-header
生成不帶django版本和遷移時間注釋的遷移文件
我們可以在對應(yīng)的model代碼中加入配置項managed=False
來忽略遷移 這個時候再執(zhí)行makemigrations
的時候則不會對該model進(jìn)行遷移代碼的生成!
還有一些其他命令,但都不常用,可以閱讀官方文檔了解
2. 在協(xié)同開發(fā)的情況下,有沖突的遷移文件時如何解決?
在類似于使用git做協(xié)同開發(fā)時,我們應(yīng)該有一個規(guī)范就是團(tuán)隊中的每一個人都應(yīng)該避免修改同一個model文件。但不可能保證每次的提交都能避免 migrations 的沖突!
這個時候我們可以使用python manage.py makemigrations --merge
進(jìn)行合并來自動修復(fù)沖突,但這只適用于簡單的model沖突合并。如果太復(fù)雜了建議閱讀django的【writing-migrations】部分進(jìn)行手動修改遷移文件
3. migrate
將遷移文件集同步到數(shù)據(jù)庫中.
如果想指定某個app遷移的話可以使用
python3 manage.py migrate [app_label]
如果想指定某個migrations文件的話可以使用
python3 manage.py migrate [app_label] [migration_name]
例如:python manage.py migrate cases 0011_auto_20220726_1440
在我們使用django-admin startproject
創(chuàng)建一個項目時后,如果需要使用django 的用戶管理、數(shù)據(jù)庫遷移等功能時就還需要配置好數(shù)據(jù)庫連接,然后執(zhí)行migrate
數(shù)據(jù)庫會生成這些表
在表【django_migrations】中會記錄每次的mirage記錄。
有個問題是,我們的項目并沒有遷移文件,那migrate是走哪拿到遷移文件進(jìn)行遷移的呢?
我們可以在【C:\Users\電腦用戶名\AppData\Local\Programs\Python\Python39\Lib\site-packages\django\contrib\auth\migrations】下找到自帶的用戶模型遷移文件。
我們還可以加參數(shù) --database DATABASE
來指定遷移的數(shù)據(jù)庫
也可以使用--plan
顯示將要執(zhí)行的遷移計劃
4. 遷移報錯怎么辦?
有些時候,我們直接對數(shù)據(jù)庫表字段進(jìn)行了修改操作,而沒有修改對應(yīng)的model代碼時,再執(zhí)行makemigrations
、migrate
會報錯!
類似如下操作:
1)我們直接在數(shù)據(jù)庫表中刪除key這個字段
2)然后在對應(yīng)的model代碼中刪除 【key】這個字段
3)這個時候再執(zhí)行makemigrations
、migrate
,會發(fā)現(xiàn)migrate
的時候報錯了
報錯的原因是我們先在數(shù)據(jù)庫中刪除了key
這個字段,然后去修改的model文件進(jìn)行遷移文件的生成和遷移。當(dāng)migrate
的時候會執(zhí)行刪除key
這個操作,但我們的表里面已經(jīng)沒有這個字段了,所以會報錯!
當(dāng)遇到這種情況的時候,我們可以使用migrate --fake
來進(jìn)行修復(fù)。
它會將將向目標(biāo)的遷移操作標(biāo)記為已應(yīng)用,但不實(shí)際運(yùn)行 SQL 來更改數(shù)據(jù)庫結(jié)構(gòu)。
另外使用migrate --fake-initial
可以對具有由CreateModel(建表操作)的遷移操作時,如果數(shù)據(jù)庫表已經(jīng)存在,則允許 Django 跳過應(yīng)用程序的初始遷移 。此選項適用于首次針對預(yù)先存在使用遷移的數(shù)據(jù)庫運(yùn)行遷移時使用。但是,此選項不會檢查匹配表名稱之外的匹配數(shù)據(jù)庫架構(gòu),因此只有在您確信現(xiàn)有架構(gòu)與初始遷移中記錄的架構(gòu)匹配時才可以安全使用!
還有的其他命令操作不常用,需要了解可以參考官方文檔
三、遷移生成的外鍵約束有必要嗎
如果有外鍵的情況下,通過migrate
會在數(shù)據(jù)庫中建立相應(yīng)的外鍵約束。這是一個很不錯的功能。在學(xué)校老師教學(xué)時,也會要求我們建立外鍵約束。
但在實(shí)際應(yīng)用中并不是一個好的選擇,而且在《阿里Java開發(fā)規(guī)范手冊》中也明確規(guī)定:【強(qiáng)制】不得使用外鍵與級聯(lián),一切外鍵概念必須在應(yīng)用層解決
為什么要做這樣的規(guī)定呢?我們可以舉一個例子來說明:
現(xiàn)在我們建立了兩個Model:【product和project】,【project】的porduct
字段,關(guān)聯(lián)Product
class Product(models.Model): id = models.AutoField(primary_key=True) created = models.DateTimeField() product_name = models.CharField(max_length=100, null=True) class Meta: db_table = 'product' class Project(models.Model): id = models.AutoField(primary_key=True) product = models.ForeignKey(to=Product, on_delete=models.PROTECT) project_name = models.CharField(max_length=100, null=True) class Meta: db_table = 'project'
然后我們進(jìn)行遷移修改數(shù)據(jù)庫表
可以看到【project】表有了一條外鍵約束的記錄
當(dāng)我們對【project】表增加一條project_id
為 1 的記錄的時候,由于【product】表不存在相應(yīng)的記錄會導(dǎo)致報錯:
可以看出,這個約束的存在,會保證表間數(shù)據(jù)的關(guān)系的完整性。更不容易出現(xiàn)臟數(shù)據(jù)。這是外鍵約束非常明顯的優(yōu)點(diǎn)!
但也存在著不可忽略的缺點(diǎn):
性能問題
我們剛建立了兩張表【project】和【product】,【project】表通過project_id
字段與【product】表做了外鍵約束。
這個時候,當(dāng)我們每次往【project】表插入數(shù)據(jù)的時候,它會先去【product】中查詢是否有對應(yīng)的關(guān)聯(lián)數(shù)據(jù),如果通過程序來控制可以不進(jìn)行這次查詢。但設(shè)立了外鍵約束,就一定會去進(jìn)行該查詢。這實(shí)際是冗余的。當(dāng)關(guān)聯(lián)的字段少的時候可能沒啥影響,但一但關(guān)聯(lián)字段多了后,這種影響就尤其明顯!
死鎖
在我們每次修改【project】數(shù)據(jù)時,都需要去【product】表檢查數(shù)據(jù),需要獲取額外的鎖。如果在高并發(fā)大流量的事務(wù)場景下,外鍵約束更容易造成死鎖!
開發(fā)/測試效率的降低
在我們?nèi)粘5臏y試過程中,經(jīng)常會遇到發(fā)現(xiàn)了一個BUG想復(fù)現(xiàn)或者方便測試的情況,會直接改數(shù)據(jù)庫表的數(shù)據(jù)來達(dá)到方便測試的效果。
雖然這及不規(guī)范,但實(shí)際情況就是能夠提升我們很多效率。這是毋庸置疑的!可是,這樣的操作也會帶來一些問題,比如因為數(shù)據(jù)導(dǎo)致的BUG,但實(shí)際并不是程序的BUG,或者發(fā)現(xiàn)不了一些潛在的BUG。
所以我的建議是:如果是業(yè)務(wù)相對復(fù)雜的話,可以在測試環(huán)境使用外鍵約束,但上了生產(chǎn)環(huán)境需要去掉!如果業(yè)務(wù)相對簡單,那完全可以刪除外鍵約束!
在django中,即便你刪除了數(shù)據(jù)庫中的外鍵約束,只要你model代碼里的外鍵關(guān)系還在,則還是可以使用它的ORM進(jìn)行外鍵操作的,沒有區(qū)別!
四、反向遷移-inspectdb
inspectdb
命令會檢查你的settings文件指向的數(shù)據(jù)庫,將其數(shù)據(jù)庫表生成對應(yīng)的django模型代碼并打印出來
也可以inspectdb
指定的模型 inspectdb product
原文鏈接:https://juejin.cn/post/7142817550047379493
相關(guān)推薦
- 2022-04-18 設(shè)置彈性布局的三列兩側(cè)對齊,最后一行樣式的處理
- 2022-07-11 Python字節(jié)碼與程序執(zhí)行過程詳解_python
- 2022-11-02 Python+requests+unittest執(zhí)行接口自動化測試詳情_python
- 2022-04-09 SpringMVC 基礎(chǔ)配置文件(簡潔版本)
- 2022-08-03 如何一鍵理清大型Python項目依賴樹_python
- 2022-12-14 python矩陣的基本運(yùn)算及各種操作_python
- 2022-04-04 HTML頁面在ios上滾動卡頓的解決方案
- 2022-05-28 Python實(shí)現(xiàn)孤立隨機(jī)森林算法的示例代碼_python
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支