Django笔记二十之手动编写migration文件

本文首发于公众号:Hunter后端
原文链接:Django笔记二十之手动编写migration文件

前面介绍过,migration 文件主要记录的是 Django 系统 model 的变化,然后通过 migrate 命令将变化适配到数据库中。

比如在某个 application 下新增了某张表,或者对某张表更改了字段,可以生成 migration 文件,然后通过 migrate 更改到数据库。

除了系统能够自动生成的,我们还可以手动创建 migration 文件来操作数据库,这个用途主要是用于比如,创建表后,需要写入一些初始化的数据的情况。

  1. 基础命令
  2. migration文件介绍
  3. 自定义migration文件
  4. RunSQL()
  5. 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 来查询数据。

如果想获取更多后端相关文章,可扫码关注阅读:
image

原文链接:https://www.cnblogs.com/hunterxiong/p/17300914.html

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Django笔记二十之手动编写migration文件 - Python技术站

(0)
上一篇 2023年4月18日
下一篇 2023年4月18日

相关文章

  • 关于Python中的同步异步阻塞与非阻塞

    关于Python中的同步异步阻塞与非阻塞,可以从以下几个方面进行说明: 同步与异步 同步和异步是针对程序内部不同部分之间的数据交互方式而言的。同步指的是请求发出之后,等待服务端返回结果后再继续执行后续的操作,而异步则是请求发出之后,不等待服务端返回结果,继续执行后续的操作。 在Python中,异步编程可以使用asyncio等库来实现,通过协程的方式来实现异步…

    python 2023年5月19日
    00
  • 深入了解python列表(LIST)

    深入了解Python列表(LIST) 在Python中,列表(list)是一种常用的数据类型,它可以存储多个元素,并且支持动态容。除了基本的增删改查操作,列表还有一些高级操作,例如列表的推导式、列表的嵌套、列表的迭代等。本文将深入讲解Python中列表的高级操作方法,包括的列表的推导式、列表的嵌套、列表的迭代等方面,并介绍一些实用技巧。 列表的推导式 在Py…

    python 2023年5月13日
    00
  • python列表切片和嵌套列表取值操作详解

    Python列表切片和嵌套列表取值操作详解 在Python中,列表是一种有序的可变序列,可以包含任意类型的元素。本攻略将细介绍如何使用Python列表切片和嵌套列表取值操作。 Python列表切片操作 Python列表切操作是指从列表获取一部元素的操作。以下是Python列表切片操作的语法: my_list[start:end:step] 其中,start是…

    python 2023年5月13日
    00
  • Python入门篇之函数

    在Python中,函数是一种非常重要的编程概念,它可以将一段代码封装成一个可重用的模块,使得代码更加简洁、易于维护和复用。本文将详细讲解Python函数的定义、调用、参数传递、返回值等相关知识点。 函数的定义 在Python中,函数的定义使用关键字 def,语法格式如下: def function_name(parameters): ""…

    python 2023年5月13日
    00
  • Python3 sys.argv[ ]用法详解

    当我们在命令行中运行 Python 脚本时,可以通过 sys.argv 获取脚本执行时传入的参数。sys.argv 是 Python 的内置模块 sys 中的一个变量,它是一个字符串列表,其中包含了命令行参数列表。sys.argv[0] 表示脚本本身的文件名, sys.argv[1:] 则表示传入的参数列表。 以下为 sys.argv 的常见用法及示例: 获…

    python 2023年6月2日
    00
  • odoo 开发入门教程系列-添加修饰

    添加修饰 我们的房地产模块现在从商业角度来看是有意义的。我们创建了特定的视图,添加了几个操作按钮和约束。然而,我们的用户界面仍然有点粗糙。我们希望为列表视图添加一些颜色,并使一些字段和按钮有条件地消失。例如,当房产已出售或取消时,“已售出”和“取消”按钮应消失,因为此时不再允许更改状态。 参考: 文档关联的主题可以查看 Views. 内联视图(Inline …

    python 2023年4月18日
    00
  • Python制作微信机器人教程详解

    Python制作微信机器人教程详解 介绍 微信机器人是一种非常常见的应用场景,它可以自动回复信息、管理群组、自动发送消息等等。Python语言具有简单易学、灵活性强等特点,成为人们实现微信机器人最常用的编程语言之一。 本教程将介绍如何使用Python编写微信机器人,并基于itchat库介绍微信机器人的开发。 步骤 准备环境 首先我们需要安装Python和it…

    python 2023年5月23日
    00
  • Python 通用的group-by归约

    下面是针对Python通用的group-by归约的使用方法的详细攻略。 什么是group-by归约 group-by归约是一种对数据进行分组操作的方法。通过该方法,可以将数据按照指定的一列或多列进行分组,然后对每组数据进行计算或操作。 通常情况下,group-by归约适合于数据集合非常大的情况,因为该方法可以将数据尽可能地合并到更小的集合(组)中,从而提高计…

    python-answer 2023年3月25日
    00
合作推广
合作推广
分享本页
返回顶部