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实现将英文单词表示的数字转换成阿拉伯数字的方法
Jul 02 Python
python登录豆瓣并发帖的方法
Jul 08 Python
Python常见异常分类与处理方法
Jun 04 Python
python+opencv轮廓检测代码解析
Jan 05 Python
python环境路径配置以及命令行运行脚本
Apr 02 Python
基于Numpy.convolve使用Python实现滑动平均滤波的思路详解
May 16 Python
Python3 列表,数组,矩阵的相互转换的方法示例
Aug 05 Python
pytorch中nn.Conv1d的用法详解
Dec 31 Python
python计算波峰波谷值的方法(极值点)
Feb 18 Python
Windows下Anaconda和PyCharm的安装与使用详解
Apr 23 Python
Python 实现 T00ls 自动签到脚本代码(邮件+钉钉通知)
Jul 06 Python
python如何设置静态变量
Sep 07 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
日本因肺炎疫情影响,这几部动漫推延播放!
2020/03/03 日漫
PHP 反向排序和随机排序代码
2010/06/30 PHP
php中session定期自动清理的方法
2015/11/12 PHP
Yii2中SqlDataProvider用法示例
2016/09/22 PHP
Laravel5.4框架使用socialite实现github登录的方法
2019/03/20 PHP
Firebug入门指南(Firefox浏览器)
2010/08/21 Javascript
基于jquery实现图片广告轮换效果代码
2011/07/07 Javascript
jquery 结合C#后台的数组对文章的关键字自动添加链接的代码
2011/07/15 Javascript
在每个匹配元素的外部插入新元素的方法
2013/12/20 Javascript
js获取通过ajax返回的map型的JSONArray的方法
2014/01/09 Javascript
jquery+easeing实现仿flash的载入动画
2015/03/10 Javascript
使用Promise链式调用解决多个异步回调的问题
2017/01/15 Javascript
Express与NodeJs创建服务器的两种方法
2017/02/06 NodeJs
用jQuery旋转插件jqueryrotate制作转盘抽奖
2017/02/10 Javascript
vue源码nextTick使用及原理解析
2019/08/13 Javascript
Vue中的循环及修改差值表达式的方法
2019/08/29 Javascript
vue中使用[provide/inject]实现页面reload的方法
2019/09/30 Javascript
jquery实现烟花效果(面向对象)
2020/03/10 jQuery
JavaScript实现公告栏上下滚动效果
2020/03/13 Javascript
0基础学习前端开发的一些建议
2020/07/14 Javascript
Python中使用 Selenium 实现网页截图实例
2014/07/18 Python
Python编程实现生成特定范围内不重复多个随机数的2种方法
2017/04/14 Python
基于python实现在excel中读取与生成随机数写入excel中
2018/01/04 Python
Python工程师面试必备25条知识点
2018/01/17 Python
Python实现的列表排序、反转操作示例
2019/03/13 Python
Python run()函数和start()函数的比较和差别介绍
2020/05/03 Python
keras的load_model实现加载含有参数的自定义模型
2020/06/22 Python
欧缇丽英国官方网站:Caudalie英国
2016/08/17 全球购物
Intimissimi德国网上商店:意大利知名内衣品牌
2018/04/03 全球购物
英国在线泳装店:Simply Swim
2019/05/05 全球购物
您在慕尼黑的跑步商店:Lauf-bar
2019/10/11 全球购物
土木工程个人自荐信范文
2013/11/30 职场文书
车辆年审委托书范本
2014/09/18 职场文书
学生上课看漫画的检讨书
2014/09/26 职场文书
老人节标语大全
2014/10/08 职场文书
CSS3中Animation实现简单的手指点击动画的示例
2021/07/15 HTML / CSS