4.8 django ORM模型迁移

ORM模型迁移

迁移命令:

  1. makemigrations:将模型生成迁移脚本。模型所在的app,必须放在settings.py中的INSTALLED_APPS中。这个命令有以下几个常用选项:
    • app_label:后面可以跟一个或者多个app,那么就只会针对这几个app生成迁移脚本。如果没有任何的app_label,那么会检查INSTALLED_APPS中所有的app下的模型,针对每一个app都生成响应的迁移脚本。
    • --name:给这个迁移脚本指定一个名字。
    • --empty:生成一个空的迁移脚本。如果你想写自己的迁移脚本,可以使用这个命令来实现一个空的文件,然后自己再在文件中写迁移脚本。
  2. 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语句。

migrations中的迁移版本和数据库中的迁移版本对不上怎么办?

  1. 找到哪里不一致,然后使用python manage.py --fake [版本名字],将这个版本标记为已经映射。
  2. 删除指定appmigrations和数据库表django_migrations中和这个app相关的版本号,然后将模型中的字段和数据库中的字段保持一致,再使用命令python manage.py makemigrations重新生成一个初始化的迁移脚本,之后再使用命令python manage.py makemigrations --fake-initial来将这个初始化的迁移脚本标记为已经映射。以后再修改就没有问题了。

更多关于迁移脚本的。请查看官方文档:https://docs.djangoproject.com/en/2.0/topics/migrations/

根据已有的表自动生成模型:

在实际开发中,有些时候可能数据库已经存在了。如果我们用Django来开发一个网站,读取的是之前已经存在的数据库中的数据。那么该如何将模型与数据库中的表映射呢?根据旧的数据库生成对应的ORM模型,需要以下几个步骤:

  1. 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`,就会将表转换为模型后的代码,显示在终端:

 ```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
 ```

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

 如果只是想要转换一个表为模型。那么可以指定表的名字。示例命令如下:

 ```python
 python manage.py inspectdb article_article > models.py
 ```
  1. 修正模型:新生成的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'
      
    • 表名:切记不要修改表的名字。不然映射到数据库中,会发生找不到对应表的错误。

  2. 执行命令python manage.py makemigrations生成初始化的迁移脚本。方便后面通过ORM来管理表。这时候还需要执行命令python manage.py migrate --fake-initial,因为如果不使用--fake-initial,那么会将迁移脚本会映射到数据库中。这时候迁移脚本会新创建表,而这个表之前是已经存在了的,所以肯定会报错。此时我们只要将这个0001-initial的状态修改为已经映射,而不真正执行映射,下次再migrate的时候,就会忽略他。

  3. Django的核心表映射到数据库中:Django中还有一些核心的表也是需要创建的。不然有些功能是用不了的。比如auth相关表。如果这个数据库之前就是使用Django开发的,那么这些表就已经存在了。可以不用管了。如果之前这个数据库不是使用Django开发的,那么应该使用migrate命令将Django中的核心模型映射到数据库中。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,968评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,601评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,220评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,416评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,425评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,144评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,432评论 3 401
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,088评论 0 261
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,586评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,028评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,137评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,783评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,343评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,333评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,559评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,595评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,901评论 2 345

推荐阅读更多精彩内容

  • 开始就错了 把自己植于一棵树里 一圈一圈地囚心 用整个春季来翻转新生 枝叶间,有流光和风的暗示 炙热枯于一种高贵的...
    简兮浅韵阅读 1,893评论 60 67
  • 今天是《断舍离》第十四天,时间过得真快,修炼时间已经一半了,大家的生活有变化吗?今天的阅读内容是第三章的“关注不扔...
    祖迩阅读 383评论 0 2
  • 今天的秋水广场,喧喧嚷嚷。人群的里边,传来歌声。我对不是自己弹着吉他的歌声不感冒,总觉得音响传递的配乐没有吉他来...
    珂静慧阅读 160评论 0 3