日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學(xué)無先后,達(dá)者為師

網(wǎng)站首頁 編程語言 正文

Django中Migrate和Makemigrations實(shí)操詳解_python

作者:曲鳥 ? 更新時間: 2022-11-06 編程語言

一、前言

當(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í)行makemigrationsmigrate會報錯!

類似如下操作:

1)我們直接在數(shù)據(jù)庫表中刪除key這個字段

2)然后在對應(yīng)的model代碼中刪除 【key】這個字段

3)這個時候再執(zhí)行makemigrationsmigrate,會發(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

欄目分類
最近更新