Django模型修改及数据迁移实现解析


Posted in Python onAugust 01, 2019

Migrations

Django中对Model进行修改是件麻烦的事情,syncdb命令仅仅创建数据库里还没有的表,它并不对已存在的数据表进行同步修改,也不处理数据模型的删除。 如果你新增或修改数据模型里的字段,或是删除了一个数据模型,你需要手动在数据库里进行相应的修改或者使用South。Django 1.7中已经集成了South的代码,提供了3个新命令:

  • migrate: 用于执行迁移动作,具有syncdb的功能
  • makemigrations: 基于当前的model创建新的迁移策略文件
  • sqlmigrate: 显示迁移的SQL语句,具有sqlall的功能

使用起来很简单,对Model做了修改后,使用makemigrations记录修改:

$ python manage.py makemigrations
Migrations for 'books':
 0003_auto.py:
  - Alter field author on book

你的Model会被扫描, 然后与migrations文件夹中以前的版本作比较, 然后生成本次迁移文件。

有了新的migration文件,就可以使用migrate修改数据库模式:

$ python manage.py migrate
Operations to perform:
 Synchronize unmigrated apps: sessions, admin, messages, auth, staticfiles, contenttypes
 Apply all migrations: books
Synchronizing apps without migrations:
 Creating tables...
 Installing custom SQL...
 Installing indexes...
Installed 0 object(s) from 0 fixture(s)
Running migrations:
 Applying books.0003_auto... OK

也可以针对单独的app生成migration:

$ python manage.py makemigrations your_app_label

也可以对数据库中的数据进行修改,首先建立一个空的migration文件:

python manage.py makemigrations --empty yourappname

文件的内容如下:

# -*- coding: utf-8 -*-
from django.db import models, migrations 
class Migration(migrations.Migration): 
  dependencies = [
    ('yourappname', '0001_initial'),
  ] 
  operations = [
  ]

如果想修改某个Model例如Person的数据,设置其name字段:

# -*- coding: utf-8 -*-
from django.db import models, migrations
 
def combine_names(apps, schema_editor):
  # We can't import the Person model directly as it may be a newer
  # version than this migration expects. We use the historical version.
  Person = apps.get_model("yourappname", "Person")
  for person in Person.objects.all():
    person.name = "%s %s" % (person.first_name, person.last_name)
    person.save()
 
class Migration(migrations.Migration):
 
  dependencies = [
    ('yourappname', '0001_initial'),
  ]
 
  operations = [
    migrations.RunPython(combine_names),
  ]

最后运行 python manage.py migrate即可。这样Person中的所有对象的name字段都设置好了。

依据Model修改关系数据库是开发中的一个重要的问题,解决这个问题可以提升开发速度,不过要在生产环境中随便使用migrate操作数据库还是很危险的,有时候需要手动修改数据库。

手动修改数据库

当处理模型修改的时候:

  • 如果模型包含一个未曾在数据库里建立的字段,Django会报出错信息。 当你第一次用Django的数据库API请求表中不存在的字段时会导致错误。
  • Django不关心数据库表中是否存在未在模型中定义的列。
  • Django不关心数据库中是否存在未被模型表示的table。

添加字段

在你的模型里添加字段。下例向Book模型添加num_pages字段:

class Book(models.Model):
  title = models.CharField(max_length=100)
  authors = models.ManyToManyField(Author)
  publisher = models.ForeignKey(Publisher)
  publication_date = models.DateField()
  **num_pages = models.IntegerField(blank=True, null=True)**
 
  def __unicode__(self):
    return self.title

运行manage.py sqlall yourappname来测试模型新的CREATE TABLE语句。

CREATE TABLE "books_book" (
  "id" serial NOT NULL PRIMARY KEY,
  "title" varchar(100) NOT NULL,
  "publisher_id" integer NOT NULL REFERENCES "books_publisher" ("id"),
  "publication_date" date NOT NULL,
  "num_pages" integer NULL
);

开启你的数据库的交互命令界面(比如,psql或者mysql,或者可以使用manage.py dbshell。 执行ALTER TABLE语句来添加新列。

ALTER TABLE books_book ADD COLUMN num_pages integer;

添加 非NULL 字段

先创建 NULL 型的字段,然后将该字段的值填充为某个默认值,然后再将该字段改为 NOT NULL 型

BEGIN;
ALTER TABLE books_book ADD COLUMN num_pages integer;
UPDATE books_book SET num_pages=0;
UPDATE books_book SET num_pages = NULL;
COMMIT;

或者

ALTER TABLE <YourTable> ADD <NewColumn> <NewColumnType> NOT NULL DEFAULT <DefaultValue>;

添加ForeignKey或ManyToManyField

添加外键即是添加key_id的integer字段,添加多对多字段是创建一个新的数据表。

删除字段

比较简单,将表中的某列删掉即可

ALTER TABLE books_book DROP COLUMN num_pages;

使用sqlite3时,会有些麻烦,sqlite3不支持删除列操作,只有有限地 ALTER TABLE 支持。你可以使用它来在表的末尾增加一列,可更改表的名称。 如果需要对表结构做更复杂的改变,则必须重新建表。重建时可以先将已存在的数据放到一个临时表中,删除原表, 创建新表,然后将数据从临时表中复制回来。

如,假设有一个 t1 表,其中有 "a", "b", "c" 三列, 如果要删除列 c :

BEGIN TRANSACTION;
CREATE TEMPORARY TABLE t1_backup(a,b);
INSERT INTO t1_backup SELECT a,b FROM t1;
DROP TABLE t1;
CREATE TABLE t1(a,b);
INSERT INTO t1 SELECT a,b FROM t1_backup;
DROP TABLE t1_backup;
COMMIT;

删除多对多关联字段

删掉多对多关联的数据表即可

DROP TABLE books_book_authors;

删除模型

删除数据表即可

DROP TABLE books_book;

数据迁移

django 项目提供了一个导出的方法 python manage.py dumpdata, 不指定 appname 时默认为导出所有的app

python manage.py dumpdata myapp > myapp.json

导出的文件内容格式:

[
 {
  "model": "myapp.person",
  "pk": 1,
  "fields": {
   "first_name": "John",
   "last_name": "Lennon"
  }
 },
 {
  "model": "myapp.person",
  "pk": 2,
  "fields": {
   "first_name": "Paul",
   "last_name": "McCartney"
  }
 }
]

数据导入:

python manage.py loaddata myapp.json

导出用户数据:

python manage.py dumpdata auth > auth.json

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python中urllib2模块的8个使用细节分享
Jan 01 Python
python smtplib模块发送SSL/TLS安全邮件实例
Apr 08 Python
Python程序中设置HTTP代理
Nov 06 Python
Python Requests库基本用法示例
Aug 20 Python
使用TensorFlow实现二分类的方法示例
Feb 05 Python
浅析Python 实现一个自动化翻译和替换的工具
Apr 14 Python
python滑块验证码的破解实现
Nov 10 Python
Python计算不规则图形面积算法实现解析
Nov 22 Python
关于numpy中eye和identity的区别详解
Nov 29 Python
python读取Kafka实例
Dec 23 Python
python路径的写法及目录的获取方式
Dec 26 Python
tensorflow实现残差网络方式(mnist数据集)
May 26 Python
Django 大文件下载实现过程解析
Aug 01 #Python
python爬虫刷访问量 2019 7月
Aug 01 #Python
用Cython加速Python到“起飞”(推荐)
Aug 01 #Python
Python爬取视频(其实是一篇福利)过程解析
Aug 01 #Python
flask框架jinja2模板与模板继承实例分析
Aug 01 #Python
Win10环境python3.7安装dlib模块趟过的坑
Aug 01 #Python
python爬虫解决验证码的思路及示例
Aug 01 #Python
You might like
拼音码表的生成
2006/10/09 PHP
使用php显示搜索引擎来的关键词
2014/02/13 PHP
php页码形式分页函数支持静态化地址及ajax分页
2014/03/28 PHP
php获取文件类型和文件信息的方法
2015/07/10 PHP
[原创]ThinkPHP让../Public在模板不解析(直接输出)的方法
2015/10/09 PHP
Yii净化器CHtmlPurifier用法示例(过滤不良代码)
2016/07/15 PHP
PhpStorm的使用教程(本地运行PHP+远程开发+快捷键)
2020/03/26 PHP
对象的类型:本地对象(1)
2006/12/29 Javascript
jQuery 页面 Mask实现代码
2010/01/09 Javascript
用示例说明filter()与find()的用法以及children()与find()的区别分析
2013/04/26 Javascript
原生js编写设为首页兼容ie、火狐和谷歌
2014/06/05 Javascript
CSS3,HTML5和jQuery搜索框集锦
2014/12/02 Javascript
js+css实现的圆角边框TAB选项卡滑动门代码分享(2款)
2015/08/26 Javascript
今天抽时间给大家整理jquery和ajax的相关知识
2015/11/17 Javascript
JavaScript对Json的增删改属性详解
2016/06/02 Javascript
js实现做通讯录的索引滑动显示效果和滑动显示锚点效果
2017/02/18 Javascript
详解angularjs 学习之 scope作用域
2018/01/15 Javascript
JavaScript变量提升和严格模式实例分析
2019/01/27 Javascript
详解实现vue的数据响应式原理
2021/01/20 Vue.js
python 自动提交和抓取网页
2009/07/13 Python
在Python 字典中一键对应多个值的实例
2019/02/03 Python
对python3 Serial 串口助手的接收读取数据方法详解
2019/06/12 Python
python脚本之一键移动自定格式文件方法实例
2019/09/02 Python
Python高级特性——详解多维数组切片(Slice)
2019/11/26 Python
python实现数字炸弹游戏
2020/07/17 Python
python搜索算法原理及实例讲解
2020/11/18 Python
Python 实现一个简单的web服务器
2021/01/03 Python
飞利浦比利时官方网站:Philips比利时
2016/08/24 全球购物
部队万能检讨书
2014/02/20 职场文书
学位证书委托书
2014/09/30 职场文书
行政复议答复书
2015/07/01 职场文书
大学副班长竞选稿
2015/11/21 职场文书
2016年第十四个公民道德宣传日活动总
2016/04/01 职场文书
SONY AN-LP1 短波有源天线放大器
2021/04/22 无线电
Python合并多张图片成PDF
2021/06/09 Python
Windows Server 2008配置防火墙策略详解
2022/06/28 Servers