django開發系列:ORM模型遷移

django開發系列:ORM模型遷移

migrattion命令:

python manage.py makemigrations
python manage.py migrate

遷移命令:

1.makemigrations:將模型生成遷移腳本。模型所在的 app,必須放在 settings.py中的INSTALLED_APPS
中。這個命令有以下幾個常用選項:
[app_label]:後面可以跟一個或者多個app,那麼就只會針對這幾個app生成遷移腳本。如果沒有任何的app_label,那麼會檢查INSTALLED_APPS中所有的app下的模型,針對每一個app都生成響應的遷移腳本。
[ --name]:給這個遷移腳本指定一個名字(就是在migrations文件夾裏的名字)
[ --empty]:生成一個空的遷移腳本。如果你想寫自己的遷移腳本,可以使用這個命令來實現一個空的文件,然後自己再在文件中寫遷移腳本。

python manage.py makemigrations app_name

2.migrate:將新生成的遷移腳本。映射到數據庫中。創建新的表或者修改表的結構。Django會生成一個記錄migrationname文件的依賴表(django_migrations)
,在執行migrate的時候會根據該表和文件依賴關係進行遷移(表裏有的不會再生成)以下一些常用的選項:
[app_label]:將某個app下的遷移腳本映射到數據庫中。如果沒有指定,那麼會將所有在INSTALLED_APPS中的app下的模型都映射到數據庫中。
app_label migrationname:將某個app下指定名字的migration文件映射到數據庫中。
[–fake]:可以將指定的遷移腳本名字添加到數據庫中。但是並不會把遷移腳本轉換爲SQL語句,修改數據庫中的表。
[–fake-initial]:將第一次生成的遷移文件版本號記錄在數據庫中。但並不會真正的執行遷移腳本。

3.showmigrations:查看某個app下的遷移文件。如果後面沒有app,那麼將查看INSTALLED_APPS中所有的遷移文件。

4.sqlmigrate:查看某個遷移文件在映射到數據庫中的時候,轉換的SQL語句。

migrate怎麼判斷哪些遷移腳本需要執行:

他會將代碼中的遷移腳本和數據庫中django_migrations中的遷移腳本進行對比,如果發現數據庫中,沒有這個遷移腳本,那麼就會執行這個遷移腳本。

migrate做了什麼事情:

  1. 將相關的遷移腳本翻譯成SQL語句,在數據庫中執行這個SQL語句。
  2. 如果這個SQL語句執行沒有問題,那麼就會將這個遷移腳本的名字記錄到django_migrations中。

執行migrate命令的時候報錯的解決辦法:

原因:

執行migrate命令會報錯的原因是。數據庫的django_migrations表中的遷移版本記錄和代碼中的遷移腳本不一致導致的。

解決辦法:

使用–fake參數:

首先對比數據庫中的遷移腳本和代碼中的遷移腳本。然後找到哪個不同,之後再使用--fake,將代碼中的遷移腳本添加到django_migrations中,但是並不會執行sql語句。這樣就可以避免每次執行migrate的時候,都執行一些重複的遷移腳本。

終極解決方案:

如果代碼中的遷移腳本和數據庫中的遷移腳本實在太多,就是搞不清了。那麼這時候就可以使用以下終極解決方案:

  1. 終極解決方案原理:就是將之前的那些遷移腳本都不用了。重新來過。要將出問題的app下的所有模型和數據庫中表保持一致,重新映射。
  2. 將出問題的app下的所有模型,都和數據庫中的表保持一致。
  3. 將出問題的app下的所有遷移腳本文件都刪掉。再在django_migrations表中將出問題的app相關的遷移記錄都刪掉。
  4. 使用makemigrations,重新將模型生成一個遷移腳本。
  5. 使用migrate --fake-initial參數,將剛剛生成的遷移腳本,標記爲已經完成(因爲這些模型相對應的表,其實都已經在數據庫中存在了,不需要重複執行了。)
  6. 可以做其他的映射了。

根據已有的表自動生成模型:

在實際開發中,有些時候可能數據庫已經存在了。如果我們用Django來開發一個網站,讀取的是之前已經存在的數據庫中的數據。那麼該如何將模型與數據庫中的表映射呢?根據舊的數據庫生成對應的ORM模型,需要以下幾個步驟:

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

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表:

那麼通過python manage.py inspectdb,就會將錶轉換爲模型後的代碼,顯示在終端:

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 manage.py inspectdb > models.py

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

如果只是想要轉換一個表爲模型。那麼可以指定表的名字。示例命令如下:

python manage.py inspectdb article_article > models.py

修正模型:新生成的ORM模型有些地方可能不太適合使用。比如模型的名字,表之間的關係等等。那麼以下選項還需要重新配置一下:

模型名:自動生成的模型,是根據表的名字生成的,可能不是你想要的。這時候模型的名字你可以改成任何你想要的。

模型所屬app:根據自己的需要,將相應的模型放在對應的app中。放在同一個app中也是沒有任何問題的。只是不方便管理。

模型外鍵引用:將所有使用ForeignKey的地方,模型引用都改成字符串。這樣不會產生模型順序的問題。另外,如果引用的模型已經移動到其他的app中了,那麼還要加上這個app的前綴。

讓Django管理模型:將Meta下的managed=False刪掉,如果保留這個,那麼以後這個模型有任何的修改,使用migrate都不會映射到數據庫中。

當有多對多的時候,應該也要修正模型。將中間表注視了,然後使用ManyToManyField來實現多對多。並且,使用ManyToManyField生成的中間表的名字可能和數據庫中那個中間表的名字不一致,這時候肯定就不能正常連接了。那麼可以通過db_table來指定中間表的名字。示例代碼如下:

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模型到表,生成的中間表的規則是:article_tags

但現在已經存在的表的名字叫做:article_tag

可以使用db_table,指定中間表的名字

tags = models.ManyToManyField(“Tag”,db_table=‘article_tag’)

class Meta:
db_table = ‘article’
表名:切記不要修改表的名字。不然映射到數據庫中,會發生找不到對應表的錯誤。

執行命令python manage.py makemigrations生成初始化的遷移腳本。方便後面通過ORM來管理表。這時候還需要執行命令python manage.py migrate --fake-initial,因爲如果不使用–fake-initial,那麼會將遷移腳本會映射到數據庫中。這時候遷移腳本會新創建表,而這個表之前是已經存在了的,所以肯定會報錯。此時我們只要將這個0001-initial的狀態修改爲已經映射,而不真正執行映射,下次再migrate的時候,就會忽略他。

將Django的核心表映射到數據庫中:Django中還有一些核心的表也是需要創建的。不然有些功能是用不了的。比如auth相關表。如果這個數據庫之前就是使用Django開發的,那麼這些表就已經存在了。可以不用管了。如果之前這個數據庫不是使用Django開發的,那麼應該使用migrate命令將Django中的核心模型映射到數據庫中。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章