共计 3584 个字符,预计需要花费 9 分钟才能阅读完成。
后面介绍过,migration 文件次要记录的是 Django 零碎 model 的变动,而后通过 migrate 命令将变动适配到数据库中。
比方在某个 application 下新增了某张表,或者对某张表更改了字段,能够生成 migration 文件,而后通过 migrate 更改到数据库。
除了零碎可能主动生成的,咱们还能够手动创立 migration 文件来操作数据库,这个用处次要是用于比方,创立表后,须要写入一些初始化的数据的状况。
- 根底命令
- migration 文件介绍
- 自定义 migration 文件
- RunSQL()
- RunPython()
1、根底命令
对于 migration 的命令有如下几条:
- makemigrations
- migrate
- sqlmigrate
- showmigrations
其中 后面三条命令在第二篇笔记中曾经介绍过应用办法,这里介绍一下 showmigrations。
这个作用次要是查看某个 application 下的 migration 文件是否曾经被更改到数据库中,能够在 Django 零碎的根目录用上面的命令测试:
python3 manage.py showmigrations blog
能够看到上面的输入:
blog
[X] 0001_initial
[X] 0002_auto_20220118_0926
[X] 0003_auto_20220121_1016
其中,后面的 [X] 示意曾经被更改到数据库中,如果咱们再对 blog 的 model 进行任意批改,而后执行 makemigrations 的操作,再次执行 showmigrations 的操作,能够看到上面的输入:
blog
[X] 0001_initial
[X] 0002_auto_20220118_0926
[X] 0003_auto_20220121_1016
[] 0004_alter_book_price
能够看到最上面的一条记录 [] 中是没有 X 的,示意这条 migration 文件没有被执行 migrate。
2、migration 文件介绍
每一次通过 makemigrations 生成的 migration 文件都存在零碎中,一个最根底的 migration 文件像上面这样:
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [('blog', '0001_initial')]
operations = [migrations.DeleteModel('Tribble'),
migrations.AddField('Author', 'rating', models.IntegerField(default=0)),
]
一个 Migration 的类下,有两个参数,一个是 dependencies,一个是 operations
dependencies 作用是定位上一个执行的 migration 文件的中央,因为每一次 migrate 的执行都是依照程序的
且他的参数是一个列表,列表的元素是一个元组,外面有两个参数,一个是 application 的名称,一个是上一次运行的 migration 文件,他是能够指定到多个 application 的,意义为在某两个 application 的 migration 文件之后再执行
operations 的作用是 migration 里须要执行的操作,能够是字段的减少、删除、批改、也能够是表的创立和删除
一个 migration 在执行 migrate 前,咱们能够手动对其批改,甚至能够齐全本人来定义
3、自定义 migration 文件
后面介绍了 migration 文件的根本构造,其中有一些对于字段和 model 的操作方法,这些操作都能够通过 makemigration 的形式主动生成。
咱们自定义的 migration 文件,与下面的保持一致即可,自定义的 migration 文件须要批改的中央是 operations 里的元素。
假如咱们有这样一个需要,创立一张根底映射表后,外面是零碎运行所必须的数据,须要在创立表后立刻写入,那么就用到了咱们这个自定义的 migration 文件。
除了对表字段或者表的批改,还有两种办法实现数据的写入,
一种是应用 SQL 语句插入,用到的 migration 的函数是 RunSQL()
一种是应用 Django 的 ORM 语句,写 python 的函数来插入,函数是 RunPython
假如创立 Blog 表的 migration file 是 0001_create_blog.py
当初须要对其插入两条数据,name 和 tagline 别离是 (‘name_1’, ‘tagline_1’) 和 (‘name_2’, ‘tagline_2’)
上面用 RunSQL() 和 RunPython() 两种形式来别离介绍。
4、RunSQL()
RunSQL() 函数承受一个字符串,或者一个数组作为参数,参数的内容都是 SQL 语句,这也是为什么函数名为 RunSQL()。
字符串的模式为残缺的 SQL 语句,比方咱们须要插入这两条数据,则是:
migrations.RunSQL("INSERT INTO blog_blog (name, tagline) values('name_x_4','tagline_1'), ('name_x_5','tagline_2');"
)
如果是作为数组传入,模式则是:
migrations.RunSQL(
sql=[
("INSERT INTO blog_blog (name, tagline) values(%s, %s), (%s, %s);",
['name_x_6', 'tagline_1', 'name_x_7', 'tagline_2']
)
]
)
在数组的传入模式中,咱们将须要插入的数据都放到一个数组中传入
reverse_sql
RunSQL() 函数除了 sql 参数,还有一个 reverse_sql 参数,用处是 sql 参数执行的 SQL 语句没有执行胜利的状况下的一种操作,个别是用于避免数据净化。
假如说咱们的 sql 为插入数据,然而因为某种原因,这条语句没有正确插入,报错了,那么零碎就会执行 reverse_sql 中的语句,作为一个可逆的操作。
以下是官网的一个应用示例:
migrations.RunSQL(sql=[("INSERT INTO musician (name) VALUES (%s);", ['Reinhardt'])],
reverse_sql=[("DELETE FROM musician where name=%s;", ['Reinhardt'])],
)
5、RunPython()
RunSQL() 函数操作的是 SQL 语句,RunPython() 参数则是 Python 函数,能够将咱们须要写入的数据都写到函数的步骤里,而后在 RunPython() 中调用
以下是应用示例:
def insert_blog_data(apps, schema_editor):
Blog = apps.get_model("blog", "Blog")
db_alias = schema_editor.connection.alias
Blog.objects.using(db_alias).create(name="name_3", tagline="tagline_3")
Blog.objects.using(db_alias).create(name="name_4", tagline="tagline_4")
class Migration(migrations.Migration):
dependencies = [("blog", "0001_initial"),
]
operations = [migrations.RunPython(insert_blog_data)
]
其中,insert_blog_data 是须要执行的函数,在这个函数里,有两个默认参数,apps 和 schema_editor
apps 能够用来获取咱们须要的 model,依据函数 apps.get_model(),
这个函数传入两个参数,一个是 application,咱们这里是 blog,
一个 model 的名称,咱们这里是 Blog
而 schema_editor 则是能够用于获取数据库的 alias
而后,数据的插入的形式就和一般的 model 的操作方法统一了。
RunPython() 函数和 RunSQL 一样,也能够输出两个参数,第二个参数作用也是用于操作失败的回退操作:
migrations.RunPython(insert_blog_data, reverse_insert)
以上就是介绍 migration 的全部内容了,下一篇笔记将介绍如何在 Django 中应用原生的 SQL 来查问数据。
本文首发于自己微信公众号:Django 笔记。
原文链接:Django 笔记二十之手动编写 migration 文件
如果想获取更多相干文章,可扫码关注浏览: