4.8 django ORM模型遷移

ORM模型遷移

遷移命令:

  1. makemigrations:將模型生成遷移腳本。模型所在的app,必須放在settings.py中的INSTALLED_APPS中。這個(gè)命令有以下幾個(gè)常用選項(xiàng):
    • app_label:后面可以跟一個(gè)或者多個(gè)app,那么就只會(huì)針對(duì)這幾個(gè)app生成遷移腳本。如果沒(méi)有任何的app_label,那么會(huì)檢查INSTALLED_APPS中所有的app下的模型,針對(duì)每一個(gè)app都生成響應(yīng)的遷移腳本。
    • --name:給這個(gè)遷移腳本指定一個(gè)名字。
    • --empty:生成一個(gè)空的遷移腳本。如果你想寫自己的遷移腳本,可以使用這個(gè)命令來(lái)實(shí)現(xiàn)一個(gè)空的文件,然后自己再在文件中寫遷移腳本。
  2. migrate:將新生成的遷移腳本。映射到數(shù)據(jù)庫(kù)中。創(chuàng)建新的表或者修改表的結(jié)構(gòu)。以下一些常用的選項(xiàng):
    • app_label:將某個(gè)app下的遷移腳本映射到數(shù)據(jù)庫(kù)中。如果沒(méi)有指定,那么會(huì)將所有在INSTALLED_APPS中的app下的模型都映射到數(shù)據(jù)庫(kù)中。
    • app_label migrationname:將某個(gè)app下指定名字的migration文件映射到數(shù)據(jù)庫(kù)中。
    • --fake:可以將指定的遷移腳本名字添加到數(shù)據(jù)庫(kù)中。但是并不會(huì)把遷移腳本轉(zhuǎn)換為SQL語(yǔ)句,修改數(shù)據(jù)庫(kù)中的表。
    • --fake-initial:將第一次生成的遷移文件版本號(hào)記錄在數(shù)據(jù)庫(kù)中。但并不會(huì)真正的執(zhí)行遷移腳本。
  3. showmigrations:查看某個(gè)app下的遷移文件。如果后面沒(méi)有app,那么將查看INSTALLED_APPS中所有的遷移文件。
  4. sqlmigrate:查看某個(gè)遷移文件在映射到數(shù)據(jù)庫(kù)中的時(shí)候,轉(zhuǎn)換的SQL語(yǔ)句。

migrations中的遷移版本和數(shù)據(jù)庫(kù)中的遷移版本對(duì)不上怎么辦?

  1. 找到哪里不一致,然后使用python manage.py --fake [版本名字],將這個(gè)版本標(biāo)記為已經(jīng)映射。
  2. 刪除指定appmigrations和數(shù)據(jù)庫(kù)表django_migrations中和這個(gè)app相關(guān)的版本號(hào),然后將模型中的字段和數(shù)據(jù)庫(kù)中的字段保持一致,再使用命令python manage.py makemigrations重新生成一個(gè)初始化的遷移腳本,之后再使用命令python manage.py makemigrations --fake-initial來(lái)將這個(gè)初始化的遷移腳本標(biāo)記為已經(jīng)映射。以后再修改就沒(méi)有問(wèn)題了。

更多關(guān)于遷移腳本的。請(qǐng)查看官方文檔:https://docs.djangoproject.com/en/2.0/topics/migrations/

根據(jù)已有的表自動(dòng)生成模型:

在實(shí)際開發(fā)中,有些時(shí)候可能數(shù)據(jù)庫(kù)已經(jīng)存在了。如果我們用Django來(lái)開發(fā)一個(gè)網(wǎng)站,讀取的是之前已經(jīng)存在的數(shù)據(jù)庫(kù)中的數(shù)據(jù)。那么該如何將模型與數(shù)據(jù)庫(kù)中的表映射呢?根據(jù)舊的數(shù)據(jù)庫(kù)生成對(duì)應(yīng)的ORM模型,需要以下幾個(gè)步驟:

  1. Django給我們提供了一個(gè)inspectdb的命令,可以非常方便的將已經(jīng)存在的表,自動(dòng)的生成模型。想要使用inspectdb自動(dòng)將表生成模型。首先需要在settings.py中配置好數(shù)據(jù)庫(kù)相關(guān)信息。不然就找不到數(shù)據(jù)庫(kù)。示例代碼如下:

     DATABASES = {
         'default': {
             'ENGINE': 'django.db.backends.mysql',
             'NAME': "migrations_demo",
             'HOST': '127.0.0.1',
             'PORT': '3306',
             'USER': 'root',
             'PASSWORD': 'root'
         }
     }
    

    比如有以下表:

    • article表:
  • tag表:
  • article_tag表:
  • front_user表:
 那么通過(guò)`python manage.py inspectdb`,就會(huì)將表轉(zhuǎn)換為模型后的代碼,顯示在終端:

 ```python
 from django.db import models
 
 class ArticleArticle(models.Model):
   title = models.CharField(max_length=100)
   content = models.TextField(blank=True, null=True)
   create_time = models.DateTimeField(blank=True, null=True)
   author = models.ForeignKey('FrontUserFrontuser', models.DO_NOTHING, blank=True, null=True)
 
   class Meta:
       managed = False
       db_table = 'article_article'
 
 class ArticleArticleTags(models.Model):
   article = models.ForeignKey(ArticleArticle, models.DO_NOTHING)
   tag = models.ForeignKey('ArticleTag', models.DO_NOTHING)
 
   class Meta:
       managed = False
       db_table = 'article_article_tags'
       unique_together = (('article', 'tag'),)
 
 class ArticleTag(models.Model):
   name = models.CharField(max_length=100)
 
   class Meta:
       managed = False
       db_table = 'article_tag'
 
 class FrontUserFrontuser(models.Model):
   username = models.CharField(max_length=100)
   telephone = models.CharField(max_length=11)
 
   class Meta:
       managed = False
       db_table = 'front_user_frontuser'
 ```

 以上代碼只是顯示在終端。如果想要保存到文件中。那么可以使用`>`重定向輸出到指定的文件。比如讓他輸出到`models.py`文件中。示例命令如下:

 ```python
 python manage.py inspectdb > models.py
 ```

 以上的命令,只能在終端執(zhí)行,不能在`pycharm->Tools->Run manage.py Task...`中使用。

 如果只是想要轉(zhuǎn)換一個(gè)表為模型。那么可以指定表的名字。示例命令如下:

 ```python
 python manage.py inspectdb article_article > models.py
 ```
  1. 修正模型:新生成的ORM模型有些地方可能不太適合使用。比如模型的名字,表之間的關(guān)系等等。那么以下選項(xiàng)還需要重新配置一下:

    • 模型名:自動(dòng)生成的模型,是根據(jù)表的名字生成的,可能不是你想要的。這時(shí)候模型的名字你可以改成任何你想要的。

    • 模型所屬app:根據(jù)自己的需要,將相應(yīng)的模型放在對(duì)應(yīng)的app中。放在同一個(gè)app中也是沒(méi)有任何問(wèn)題的。只是不方便管理。

    • 模型外鍵引用:將所有使用ForeignKey的地方,模型引用都改成字符串。這樣不會(huì)產(chǎn)生模型順序的問(wèn)題。另外,如果引用的模型已經(jīng)移動(dòng)到其他的app中了,那么還要加上這個(gè)app的前綴。

    • 讓Django管理模型:將Meta下的managed=False刪掉,如果保留這個(gè),那么以后這個(gè)模型有任何的修改,使用migrate都不會(huì)映射到數(shù)據(jù)庫(kù)中。

    • 當(dāng)有多對(duì)多的時(shí)候,應(yīng)該也要修正模型。將中間表注視了,然后使用ManyToManyField來(lái)實(shí)現(xiàn)多對(duì)多。并且,使用ManyToManyField生成的中間表的名字可能和數(shù)據(jù)庫(kù)中那個(gè)中間表的名字不一致,這時(shí)候肯定就不能正常連接了。那么可以通過(guò)db_table來(lái)指定中間表的名字。示例代碼如下:

      class Article(models.Model):
       title = models.CharField(max_length=100, blank=True, null=True)
       content = models.TextField(blank=True, null=True)
       author = models.ForeignKey('front.User', models.SET_NULL, blank=True, null=True)
       # 使用ManyToManyField模型到表,生成的中間表的規(guī)則是:article_tags
       # 但現(xiàn)在已經(jīng)存在的表的名字叫做:article_tag
       # 可以使用db_table,指定中間表的名字
       tags = models.ManyToManyField("Tag",db_table='article_tag')
      
       class Meta:
           db_table = 'article'
      
    • 表名:切記不要修改表的名字。不然映射到數(shù)據(jù)庫(kù)中,會(huì)發(fā)生找不到對(duì)應(yīng)表的錯(cuò)誤。

  2. 執(zhí)行命令python manage.py makemigrations生成初始化的遷移腳本。方便后面通過(guò)ORM來(lái)管理表。這時(shí)候還需要執(zhí)行命令python manage.py migrate --fake-initial,因?yàn)槿绻皇褂?code>--fake-initial,那么會(huì)將遷移腳本會(huì)映射到數(shù)據(jù)庫(kù)中。這時(shí)候遷移腳本會(huì)新創(chuàng)建表,而這個(gè)表之前是已經(jīng)存在了的,所以肯定會(huì)報(bào)錯(cuò)。此時(shí)我們只要將這個(gè)0001-initial的狀態(tài)修改為已經(jīng)映射,而不真正執(zhí)行映射,下次再migrate的時(shí)候,就會(huì)忽略他。

  3. Django的核心表映射到數(shù)據(jù)庫(kù)中:Django中還有一些核心的表也是需要?jiǎng)?chuàng)建的。不然有些功能是用不了的。比如auth相關(guān)表。如果這個(gè)數(shù)據(jù)庫(kù)之前就是使用Django開發(fā)的,那么這些表就已經(jīng)存在了??梢圆挥霉芰?。如果之前這個(gè)數(shù)據(jù)庫(kù)不是使用Django開發(fā)的,那么應(yīng)該使用migrate命令將Django中的核心模型映射到數(shù)據(jù)庫(kù)中。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 開始就錯(cuò)了 把自己植于一棵樹里 一圈一圈地囚心 用整個(gè)春季來(lái)翻轉(zhuǎn)新生 枝葉間,有流光和風(fēng)的暗示 炙熱枯于一種高貴的...
    簡(jiǎn)兮淺韻閱讀 1,934評(píng)論 60 67
  • 今天是《斷舍離》第十四天,時(shí)間過(guò)得真快,修煉時(shí)間已經(jīng)一半了,大家的生活有變化嗎?今天的閱讀內(nèi)容是第三章的“關(guān)注不扔...
    祖邇閱讀 465評(píng)論 0 2
  • 今天的秋水廣場(chǎng),喧喧嚷嚷。人群的里邊,傳來(lái)歌聲。我對(duì)不是自己彈著吉他的歌聲不感冒,總覺(jué)得音響傳遞的配樂(lè)沒(méi)有吉他來(lái)...
    珂靜慧閱讀 189評(píng)論 0 3

友情鏈接更多精彩內(nèi)容