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
  • 根据需求重复操作

这个工作流程在大多数情况下都可以搞定,但如果事情没有按预期进行,还可以列出或者取消应用迁移帮助我们操作。

Django迁移的更多相关文章

  1. django迁移:全局、局部

    django迁移:全局.局部 django 数据库迁移(migrate)应该知道的一些事 https://blog.csdn.net/stonesola/article/details/6975861 ...

  2. 关于Django迁移出现问题

    关于Django迁移出现问题 源码: #coding:utf- from django.db import models # Create your models here. class BookIn ...

  3. Django迁移数据库报错

    Django迁移数据库报错 table "xxx" already exists错误 django在migrate时报错django migrate error: table 'x ...

  4. 向同一个模型的外键反向关联名称产生了冲突 Django迁移

    向同一个模型的外键反向关联名称产生了冲突 一个模型中有两个外键指向同一张表时,创建迁移模型时报错:" HINT: Add or change a related_name argument ...

  5. django迁移数据库报错解决

    迁移数据库时提示之前的项目中模型未引入 如图 我在创建新的工程时,迁移数据模型时发现出错,错误提示关联模型未被解决,提示的模型是之前项目中定义的,本项目并没有用到.于是在不知道错误原因下,我重装dja ...

  6. HelloDjango 系列教程:第 04 篇:Django 迁移、操作数据库

    文中涉及的示例代码,已同步更新到 HelloGitHub-Team 仓库 我们已经编写了博客数据库模型的代码,但那还只是 Python 代码而已,django 还没有把它翻译成数据库语言,因此实际上这 ...

  7. django迁移脚本

    执行migrate报错的解决办法: 想知道migrate为什么报错,需要先了解migrate到底做了什么事情 migrate做了什么事情? 1.将相关的迁移脚本翻译成sql语句,然后在数据库中执行 2 ...

  8. 【Django】Django迁移数据库

    我们已经编写了博客数据库模型的代码,但那还只是 Python 代码而已,Django 还没有把它翻译成数据库语言,因此实际上这些数据库表还没有真正的在数据库中创建 为了让 Django 完成翻译,创建 ...

  9. django迁移model到别的app中

    举例: 移动 users.AccessKey 到 authentication.AccessKey中 1. 移动models到新的app中 $ mv users/models/access_key.p ...

随机推荐

  1. Linux C Socket编程:文件上传

    一个服务端等待, 客户端上传文件到服务端,通过输入要上传的文件名,目前只做到仅对当前执行文件的目录下的文件,应该在服务端收到文件路径之后进行处理的. 服务端代码: #include <netin ...

  2. sha256C代码例子

    a.c #include <stdio.h>#include <string.h>#include <openssl/sha.h> 1 int main(int a ...

  3. PAT 甲级 1036 Boys vs Girls (25 分)(简单题)

    1036 Boys vs Girls (25 分)   This time you are asked to tell the difference between the lowest grade ...

  4. python 创建虚拟环境(virtualenv)

    原文地址:https://www.jianshu.com/p/2645d8f2e690 另附连接:Linux环境下虚拟环境virtualenv安装和使用 virtualenv 安装 1.Install ...

  5. 如何提高程序员的键盘使用效率?——ASE第一次作业

    引言 对于程序员来说,键盘输入是我们工作的基本方式,当你的手指在键盘上飞起来的时候,不但能够提高工作效率,还常常引来旁人羡慕的目光.下面将从不同方面介绍一些提高键盘使用效率的方法. 程序员最主要的文字 ...

  6. java、ruby、python、php等如何生成excel文档?

    excel在我们日常工作生活中会经常用到,通常我们都是用office软件去编写文档.但是对于格式一致的excel文档,如果还是使用人工完成,那绝不是我们软件工程师的姿态了~ 下面我就介绍一种方法,不需 ...

  7. 【VS开发】【miscellaneous】windows(64位)下使用curl命令

    windows(64位)下使用curl命令 Curl命令可以通过命令行的方式,执行Http请求.在Elasticsearch中有使用的场景,因此这里研究下如何在windows下执行curl命令. 工具 ...

  8. 最新 美团java校招面经 (含整理过的面试题大全)

    从6月到10月,经过4个月努力和坚持,自己有幸拿到了网易雷火.京东.去哪儿.美团等10家互联网公司的校招Offer,因为某些自身原因最终选择了美团.6.7月主要是做系统复习.项目复盘.LeetCode ...

  9. 安卓AES加密

    一:什么是AES加密 AES高级加密标准(英语:Advanced Encryption Standard,缩写:AES),在密码学中又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准. ...

  10. Java 文件下载工具类

    Java 文件下载工具类 import org.slf4j.Logger; import org.slf4j.LoggerFactory; private static Logger logger = ...