Django迁移
学习目标:
- 如何在不编写任何SQL语句的情况下创建数据库表
- 更改model如何自动修改数据库
- 如何还原对数据库所做的更改
迁移能解决的问题
如果你不了解Django或者WEB开发,肯定是不熟悉数据库迁移的概念的。
在学习它之前,首先我们需要明确它是干什么的,Django使用它旨在与关系型数据库结合使用,将数据存储在PostgreSQL
,Mysql
或者SQLite
等关系型数据库管理系统中.
在关系数据库中,数据以表格形式组织。数据库表具有一定数量的列,但它可以包含任意数量的行。每列都有一个特定的数据类型,如某个特定最大长度的字符串或正整数。所有表及其列及其各自数据类型的描述称为数据库模式。
Django支持的所有数据库系统都使用语言SQL来创建,读取,更新和删除关系数据库中的数据。SQL还用于创建,更改和删除数据库表本身。
直接使用SQL可能非常麻烦,因此为了让我们的开发工作更加轻松,Django附带了一个对象关系映射器,简称ORM。ORM将关系数据库映射到面向对象编程的世界。可以在Python中编写Django模型,而不是在SQL中定义数据库表。模型定义数据库字段,这些字段对应于其数据库表中的列。
以下是Django模型类如何映射到数据库表的示例:
但是只是在Python文件中定义一个模型类并不会使数据库表格无处不在。创建数据库表来存储Django模型是数据库迁移的工作。此外,无论何时对模型进行更改(如添加字段),都必须更改数据库。迁移也处理这个问题。
以下是Django迁移让我们的开发工作更加轻松的几种方式:
1、不使用SQL对数据库进行修改
在Django中,如果没有迁移,就必须在使用的时候链接到数据库并且输入一堆SQL命令,或者使用一些图形工具在每次要更改模型定义时修改数据库模式。
在Django中,迁移主要是用Python代码完成的,因此除非你有非常高级的需求用法,否则你不需要操作任何SQL。
2、避免重复
如果创建模型后,编写sql语句创建数据库表,则会造成重复现象。
但是从模型中生成迁移,就能确保不会重复
3、确保模型定义和数据模式同步
通常,我们会有多个数据库实例,例如,团队中每个开发人员的一个数据库,用于测试的数据库和包含实时数据的数据库。
如果没有迁移,则必须对每个数据库执行任何模式更改,并且必须跟踪已对哪个数据库进行了哪些更改。
使用Django Migrations,就可以轻松地使多个数据库与模型保持同步。
4、跟踪版本控制(git)中的数据库模式更改
像Git这样的版本控制系统非常适合代码,但对数据库模式来说并不是那么多。
由于迁移在Django中是普通的Python,因此您可以将它们放在版本控制系统中,就像任何其他代码一样。
创建迁移
在迁移之前首先得创建一个Django项目,具体怎么创建就不做过多赘述啦。直接开始吧
在做迁移之前,我们首先要创建模型。在app01/models.py
中添加此类
class User(models.Model):
name = models.CharField(max_length=32)
password = models.CharField(max_length=64)
一个最简单的用户模型类。
模型创建完成之后的第一件事就是为他创建迁移。
> python manage.py makemigrations
# 有的同学执行了以上命令后会发现不行,报错了
"""
File "manage.py", line 16
) from exc
^
SyntaxError: invalid syntax
"""
这就很难受了,为什么呢,因为随着时间的增长,Django的版本已经更新到2.3以后了,而在Django1.7以后,执行以上代码都会报这个错误。我们需要将python替换成python3
> python3 manage.py makemigrations
"""
Migrations for 'hello_world':
hello_world/migrations/0001_initial.py
- Create model User
"""
这就成功了!!!
执行成功后,在migrations目录现在包含一个新文件:0001_initial.py
"""
当我们运行完 makemigrations 命令,如果你没有配置数据库,它还会自动创建db.sqlite3数据库.这个是Django默认的配置,同时也是SQLite独有的配置。如果是其他数据库的话,例如:Mysql、PostgreSQL等,就必须在运行之前自己创建数据库了
"""
迁移成功后,我们接着来查看你的数据库,会发现它虽然被创建出来了,但是他依然是空的。
> python3 manage.py dbshell
SQLite version 3.24.0 2018-06-04 14:10:15
Enter ".help" for usage hints.
sqlite> .tables
sqlite>
应用迁移
虽然现在我们已经创建了迁移工作,但是要想要实际在数据库中进行任何修改,就必须执行migrate
命令:
> python3 manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, hello_world, sessions
Running migrations:
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
Applying admin.0002_logentry_remove_auto_add... OK
Applying admin.0003_logentry_add_action_flag_choices... OK
Applying contenttypes.0002_remove_content_type_name... OK
Applying auth.0002_alter_permission_name_max_length... OK
Applying auth.0003_alter_user_email_max_length... OK
Applying auth.0004_alter_user_username_opts... OK
Applying auth.0005_alter_user_last_login_null... OK
Applying auth.0006_require_contenttypes_0002... OK
Applying auth.0007_alter_validators_add_error_messages... OK
Applying auth.0008_alter_user_username_max_length... OK
Applying auth.0009_alter_user_last_name_max_length... OK
Applying auth.0010_alter_group_name_max_length... OK
Applying auth.0011_update_proxy_permissions... OK
Applying hello_world.0001_initial... OK
Applying sessions.0001_initial... OK
执行完这条命令,会发现有很多输出,根据输出来看,我们的迁移已经成功应用,那么这些迁移中还有一些我们不知道的东西,它们来自于哪里呢?
还记得配置文件中的INSTALLED_APPS
吗?其中列出的其他一些应用程序也带有迁移功能,migrate
管理命令默认情况下会为所有已安装的应用程序应用迁移。
再来看一下数据库:
SQLite version 3.24.0 2018-06-04 14:10:15
Enter ".help" for usage hints.
sqlite> .tables
auth_group django_admin_log
auth_group_permissions django_content_type
auth_permission django_migrations
auth_user django_session
auth_user_groups hello_world_user
auth_user_user_permissions
sqlite>
现在我们的数据库已经出现了多个表,我们可以从他们的名字上来了解他们的作用。
# 可以通过.schema命令查看已经生成的表
sqlite> .schema --indent hello_world_user
CREATE TABLE IF NOT EXISTS "hello_world_user"(
"id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,
"name" varchar(32) NOT NULL,
"password" varchar(64) NOT NULL
);
"""
.schema命令打印出CREATE将执行以创建表的语句。该参数--indent将sql语句格式化。即使不熟悉SQL语法,也可以看到hello_world_user表的模式反映了user模型的字段。
"""
如果你再次进行迁移的话,会发现不会将所有的模型表重新执行一遍,因为Django会记住已经应用了那些迁移,不会对已经迁移过的,在重新运行。
模型修改
你的model文件一定不是一成不变的,随着你项目的完善,功能的添加,你的模型肯定会发生变化,可以添加、删除字段或者更改类型还有选项。
在更改模型类的时候,肯定还需要更改用于存储这些模型的数据库表。如果模型定义与当前数据模式不匹配,很可能就会报错:django.db.utils.OperationalError
具体更改方法:
依次执行:
> python3 manage.py makemigrations
> python3 manage.py migrate
列出迁移
如果想要知道项目中存在那些迁移,可以直接通过以下命令查看
python3 manage.py showmigrations
取消应用迁移
创建以及应用迁移都已经搞定了,知道如如何通过它们去更改数据库模式,但是有些时候我们可能需要执行一些撤销操作以切换回早期的数据库模式,比如:
- 测试公司项目的中写的迁移
- 迁移之后出现bug
- 同时处理不同数据库修改的多个功能
- 想要还原在数据库中具老架构的备份
所以这个时候就需要取消迁移来帮助我们了。
> python3 manage.py migrate hello_world 0001_initial
执行它就可以将迁移取消应用,也意味着对数据库的更改也被取消了
取消应用迁移不会删除其迁移文件。下次运行该migrate
命令时,将再次应用迁移。
"""
不要将未应用的迁移与您最常用的文本编辑器中的撤消操作混淆。
并非所有数据库操作都可以完全还原。如果从模型中删除字段,创建迁移并应用它,Django将从数据库中删除相应的列。
取消应用迁移将重新创建列,但它不会带回存储在该列中的数据!
"""
总结
Django迁移的基本步骤:
- 创建或更新模型类
- 执行
python3 manage.py makemigrations <app name(可不写)>
- 执行
python3 manage.py migrate
迁移所有内容或python3 manage.py migrate <app name>
迁移单个app - 根据需求重复操作
这个工作流程在大多数情况下都可以搞定,但如果事情没有按预期进行,还可以列出或者取消应用迁移帮助我们操作。