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. 打印变量地址-0x%08x

    地址是8个16进制数. 1.8个16进制数:相当于32个二进制数.4G内存刚好可以用32位的二进制表示出来.2.因为变量或函数等等在运行时都是存储在内存中的,所以你用取地址符当然是取出计算机内存中的地 ...

  2. Flutter布局基本情况总结:

    1.一行内容,发布两边: 效果: Flex( direction: Axis.horizontal, children: <Widget>[ Expanded( flex: , child ...

  3. 26Flutter 日期 和时间戳/格式化日期库/flutter异步/ 官方自带日期组件showDatePicker、时间组件showTimePicker以及国际化

    /* 一.Flutter日期和时间戳 日期转换成时间戳 var now=newDateTime.now(); print(now.millisecondsSinceEpoch); //单位毫秒,13位 ...

  4. hue集成mysql找不到 libmysqlclient.so.16问题解决

    首先我的配置文件如下,这个是没有问题的 但是在重启hue连接mysql时,却发生了如下问题: 这个错误的意思就是没有找到libmysqlclient_r.so.16这个文件,可能是我安装的mysql有 ...

  5. Day4作业:蛋疼CRM系统

    先上流程图,还得27寸4K显示器,画图各种爽: ReadMe: 运行程序前的提示: 1.抱歉,你得装prettytable模块...... 2.还得抱歉,如果shell中运行,最好把字体调得小点,表格 ...

  6. Ubuntu 14.04 apache安装配置

    http://jingyan.baidu.com/article/6d704a130c8a0d28da51ca5f.html Ubuntu 14.04 apache安装配置 1.安装 ~# apt-g ...

  7. LeetCode_121. Best Time to Buy and Sell Stock

    121. Best Time to Buy and Sell Stock Easy Say you have an array for which the ith element is the pri ...

  8. MySQL复制表结构

    示例SQL: create table testdb.test_table_back like testdb.test_table

  9. nmap探测大网络空间中的存活主机

    前言 扫描大网络空间中的存活主机 实现 nmap -v -sn -PE -n --min-hostgroup 1024 --min-parallelism 1024 -oX nmap_output.x ...

  10. springmvc+mybatis多数据源配置,AOP注解动态切换数据源

    springmvc与springboot没多大区别,springboot一个jar包配置几乎包含了所有springmvc,也不需要繁琐的xml配置,springmvc需要配置多种jar包,需要繁琐的x ...