Django模型修改及数据迁移实现解析
作者:再见紫罗兰 发布时间:2022-05-20 10:20:40
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
来源:https://www.cnblogs.com/linxiyue/p/4106514.html


猜你喜欢
- 刚接触 Go 语言时,就听说有一个叫rune的数据类型,即使查阅过一些资料,对它的理解依旧比较模糊,加之对陌生事物的天然排斥,在之后很长一段
- opencv中有多种色彩空间,包括 RGB、HSI、HSL、HSV、HSB、YCrCb、CIE XYZ、CIE Lab8种,使用中经常要遇到
- 中小站点简单备份策略基于drupal的中小行网站,我们可以使用backup_migrate模块,该模块提供了定期备份的功能,备份的时间、保留
- 背景在开发中,我们常常会遇到一些耗时任务,举个例子:上传并解析一个 1w 条数据的 Excel 文件,最后持久化至数据库。在我的程序中,这个
- 爬虫请求头网页获取:通过urlopen来进行获取requset.urlopen(url,data,timeout)第一个参数url即为URL
- 今天遇到一个需要用javascript将url中的某些参数替换的需求,想起了不久前从网上淘到了一个parseUrl函数,正好可以借此实现,代
- 这里首先给出来我很早之前写的一篇博客,Python实现去除列表中重复元素的方法小结【4种方法】,感兴趣的话可以去看看,今天是在实践过程中又积
- Google Chrome 的发布,使我们更加的注重基于 WebKit 核心的浏览器的表现情况,但我们很多时候“不小心”就会出现问题。考虑下
- keras.utils.to_categorical这个方法,源码中,它是这样写的:Converts a class vector (int
- 前言因为前面的文章中已经涉及到了登录智慧校园的验证码处理问题,所以本文将略过此过程。如登录时遇到验证码的情况,请参考此文。其实第一次使用有验
- 一、前言设计应用程序时,有时不希望将一个不太相关的功能集成到程序中,或者是因为该功能与当前设计的应用程序联系不大,或者是因为该功能已经可以使
- 本文实例讲述了python使用pil生成图片验证码的方法。分享给大家供大家参考。具体实现方法如下:# -*- coding: utf-8 -
- 1.基数排序基数排序的基本思想是先将数字按照个位数上数字的大小进行排序,排序之后再将已经排过序的数字再按照十位数上数字的大小进行排序,依次推
- 一、什么是ttkbootstrap?官方文档 [较慢]:https://ttkbootstrap.readthedocs.io/en/lat
- torch.arange函数详解官方文档:torch.arange函数原型arange(start=0, end, step=1, *, o
- 我们在操作 ini 配置文件的时候 可以使用 Python 的 configparser 库具体使用方法如下:from configpars
- 本文实例讲述了Python实现动态加载模块、类、函数的方法。分享给大家供大家参考,具体如下:动态加载模块: 方式1:系统函数__import
- 为了给你的对像添加一个行级功能,那就定义一个自定义方法。 有鉴于manager经常被用来用一些整表操作(table-wide),模型方法应该
- 本文实例讲述了Python中的is和id用法。分享给大家供大家参考。具体分析如下:(ob1 is ob2) 等价于 (id(ob1) ==
- 在说这两兄弟前,先做一个实验:我在Win7下新建左一个文本文件test.txt,然后用记事本打开输入如下内容,保存然后用UltraEdit以