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

标签:django,模型,修改,数据,迁移
0
投稿

猜你喜欢

  • Python 恐龙跑跑小游戏实现流程

    2021-10-23 19:42:59
  • asp如何让用户也能修改密码?

    2010-05-13 16:41:00
  • 浏览器的字体等宽空格

    2008-08-28 12:25:00
  • python中文件操作与异常的处理图文详解

    2021-09-04 16:04:33
  • Python 在 VSCode 中使用 IPython Kernel 的方法详解

    2023-07-25 10:10:23
  • Python pandas按行、按列遍历DataFrame的几种方式

    2021-02-22 07:11:12
  • 6个网站改版时需要注意的问题

    2010-02-26 10:47:00
  • 基于python指定包的安装路径方法

    2023-06-04 03:10:02
  • tensorflow使用指定gpu的方法

    2022-10-23 16:00:31
  • Python数据类型之String字符串实例详解

    2022-01-08 11:38:50
  • js实现屏蔽默认快捷键调用自定义事件示例

    2023-09-05 09:28:31
  • python 实现判断ip连通性的方法总结

    2023-06-24 22:36:53
  • 互联网产品交互事件分析

    2009-10-06 15:23:00
  • ASP的数据命名有什么规则吗?

    2009-10-28 18:23:00
  • appium+python adb常用命令分享

    2022-12-27 09:16:24
  • Linux+php+apache+oracle环境搭建之CentOS下安装Oracle数据库

    2023-10-08 01:02:56
  • 无级分类的多级联动

    2020-07-02 12:53:12
  • ASP与MySQL的连接[图文教程]

    2010-03-14 11:21:00
  • 浅谈python在提示符下使用open打开文件失败的原因及解决方法

    2023-12-07 18:31:33
  • np.newaxis 实现为 numpy.ndarray(多维数组)增加一个轴

    2021-02-14 07:48:20
  • asp之家 网络编程 m.aspxhome.com