zoukankan      html  css  js  c++  java
  • Django模型修改及数据迁移

    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。

    添加字段

    1. 在你的模型里添加字段。下例向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 
    1. 运行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
      );
    1. 开启你的数据库的交互命令界面(比如,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
    

      

  • 相关阅读:
    数据库如何部署上线阅读总结
    Nginx解决防盗链,服务器宕机,跨域,防DDOS
    跨域和表单重复提交
    Socet
    Redis发布订阅
    MySQL和Oracle的区别
    Redis事务、持久化、发布订阅
    Redis主从复制和哨兵模式
    Idea中使用Redis的Java客户端和Jedis
    Redis介绍及命令
  • 原文地址:https://www.cnblogs.com/linxiyue/p/4106514.html
Copyright © 2011-2022 走看看