精华内容
参与话题
问答
  • python3 migrations 使用

    千次阅读 2019-06-04 18:19:53
    config.js HOSTNAME = '192.168.195.161' PORT = '3306' DATABASE = 'medicine_settle' USERNAME = 'admin' PASSWORD = 'admin' DB_URI = 'mysql+mysqldb://{}:{}@{}:{}/{}?charset=utf8'.format(USERNAME,PASSW...

    config.js

    HOSTNAME = '192.168.195.161'
    PORT     = '3306'
    DATABASE = 'medicine_settle'
    USERNAME = 'admin'
    PASSWORD = 'admin'
    DB_URI = 'mysql+mysqldb://{}:{}@{}:{}/{}?charset=utf8'.format(USERNAME,PASSWORD,HOSTNAME,PORT,DATABASE)
    SQLALCHEMY_DATABASE_URI = DB_URI
    
    SQLALCHEMY_TRACK_MODIFICATIONS = True
    

    exts.js

    #encoding: utf-8
    from flask_sqlalchemy import SQLAlchemy
    db = SQLAlchemy()
    

    manage.py

    from flask_script import Manager
    from flask_migrate import Migrate, MigrateCommand
    from exts import db
    from migrate_demo import app
    
    # python manage.py db init
    # python manage.py db migrate
    # python manage.py db upgrade
    # 模型  ->  迁移文件  ->  表
    
    manager = Manager(app)
    
    # 1. 要使用flask_migrate,必须绑定app和db
    migrate = Migrate(app, db)
    
    # 2. 把MigrateCommand命令添加到manager中
    manager.add_command('db', MigrateCommand)
    
    if __name__ == '__main__':
        manager.run()
    
    

    migrate_demo.py

    #encoding: utf-8
    from flask import Flask
    from exts import db
    import config
    app = Flask(__name__)
    app.config.from_object(config)
    db.init_app(app)
    # 新建一个article模型,采用models分开的方式
    # flask-scrpts的方式
    
    @app.route('/')
    def hello_world():
        return 'Hello World!'
    
    if __name__ == '__main__':
        app.run(debug=True)
    
    

    models.py

    #encoding: utf-8
    
    
    from .exts import db
    
    class Article(db.Model):
        __tablename__ = 'article'
        id = db.Column(db.Integer,primary_key=True,autoincrement=True)
        title = db.Column(db.String(100),nullable=False)
        content = db.Column(db.Text,nullable=False)
        tags = db.Column(db.String(100),nullable=False)
    
    

    在这里插入图片描述

    python manage.py db init [只运行一次就行,以后不用再运行]

    python manage.py db migrate [更新的话需要每次都运行]

    python manage.py db upgrade [更新的话需要每次都运行]

    模型 -> 迁移文件 -> 表

    需要特别注意的事是,这里的使用方式与mybatis逆向工程是相反的,mybatis 是根据表生成实体类以及mapper.xml,而python的migrations则是根据你写的实体生成表。如果没有配置好,migrations 会将你数据库中的表删除,再创建。造成严重的不可挽回的损失。切记切记!!!

    展开全文
  • 构造函数 //初始化DbMigrationsConfiguration DbMigrationsConfiguration() EF框架 Code First模式开启数据迁移 //获取或设置一个值,该值指示在迁移数据库时是否可以使用自动迁移。 AutomaticMigrationsEnabled =...

    构造函数

    //初始化DbMigrationsConfiguration
    DbMigrationsConfiguration()
    

    EF框架 Code First模式开启数据迁移

    //获取或设置一个值,该值指示在迁移数据库时是否可以使用自动迁移。
                AutomaticMigrationsEnabled = true;
    //获取或设置一个值,指示在自动迁移期间数据丢失是否可接受。 如果设置为false,如果数据丢失可能会在自动迁移过程中发生,则会引发异常。
                AutomaticMigrationDataLossAllowed=true;
    
    

    类参考

    属性 说明
    AutomaticMigrationDataLossAllowed 获取或设置一个值,指示在自动迁移期间数据丢失是否可接受。 如果设置为false,如果数据丢失可能会在自动迁移过程中发生,则会引发异常。
    AutomaticMigrationsEnabled 获取或设置一个值,该值指示在迁移数据库时是否可以使用自动迁移
    CodeGenerator 获取或设置脚手架迁移时要使用的代码生成器。
    CommandTimeout 获取或设置用于迁移中各个命令的超时值。 空值表示将使用基础提供程序的默认值。
    ContextKey 获取或设置用于区分属于此配置的迁移与使用同一数据库的属于其他配置的迁移的字符串。 此属性允许将来自多个不同模型的迁移应用于单个数据库。
    ContextType 获取或设置表示要迁移的模型的派生DbContext。
    MigrationsAssembly 获取或设置包含基于代码的迁移的程序集。
    MigrationsDirectory 获取或设置存储基于代码的迁移的子目录。请注意,必须将此属性设置为Visual Studio项目根目录下子目录的相对路径; 它不能设置为绝对路径。
    MigrationsNamespace 获取或设置用于基于代码的迁移的命名空间。
    TargetDatabase 获取或设置一个值以覆盖要迁移的数据库的连接。

    此谷歌翻译的文档,只作参考。
    原文地址

    展开全文
  • #转载 Migrantion 是 Django 最有用的的特性之一,但是对于我来说改变 Model 这是一个很可怕的任务。尽管能够阅读文档,我仍然很害怕 migration 的冲突或者丢失数据,或者需要手动处理 migration 文件,或者这样那样...

    #转载

    Migrantion 是 Django 最有用的的特性之一,但是对于我来说改变 Model 这是一个很可怕的任务。尽管能够阅读文档,我仍然很害怕 migration 的冲突或者丢失数据,或者需要手动处理 migration 文件,或者这样那样的事情。事实上,一旦理解它们,migration 是很酷的、很有用的。关于以上的问题你将不会有任何疑问。

    翻译自 Oana Ratiu 的《Django Migrations and How to Manage Conflicts》

    我一直不能找到一些有价值的文章和文档,也许在某个地方,所有的方法都可以解决冲突。然而从来没有人在 Google 上仔细的搜索。在这些问题上我会尝试收集一些不同角度。主要的是,我会尝试去解释你可以在项目中找到的那些 migrations,如何解决 migration 的冲突,和一些数据迁移的。我会假定你是有 Django、Python 和 GIT 的使用经验。

    在 Django 的文档中对 migrations 的简单定义:

    Migrantion 是 Django 根据你的想法,改变 Model (添加字段、删除 Model 等)到数据库中的方法。它们大多数是自动的,但是你需要知道什么时候执行 migrations,执行它们时候,你可能会遇到的问题。

    无论你选择是的 PostgreSQL, MySQL 还是 SQLite,你都可以使用一套命令去管理数据库。我将会较多的谈论关于 makemigrations 命令,它会基于你对 Model 的改动,然后创建新的 migrations。还有就是 migrate 命令,它会使 migrations 生效,完成后使它们失效和列出它们状态。

    我的 migrations 在哪里?
    在你的工程中,你可以找到 migrations 文件(.py 的文件)在 migrations 的文件夹里。确保文件夹中有 init.py 这个文件,如果没有这个文件,那么还是没有效果。

    在你的 settings 文件中每个已安装的 app,你都可以找到对应得 migration 文件。例如,你可以在…/lib/python2.7/site-packages/django/contrib/auth/migrations 找到 User 的 migration。

    你可以在你的数据库中找到 django_migrations 表,它列出了已经生效的 migrations。这是为了在切换分支的时候产生不同的 migrations,让你忘记执行到了哪里。

    my_data=# select * from django_migrations;
    id | app | name | applied
    ----±--------------±------------------------±------------------------------
    … | … | … | …
    10 | myapp | 0001_initial | 2016-03-17 07:22:30.329448+00
    11 | myapp | 0002_auto_20160316_0909 | 2016-03-17 07:22:30.956985+00
    12 | myapp | 0003_auto_20160318_1345 | 2016-03-18 13:45:23.895839+00
    … | … | … | …
    (16 rows)
    1

    my_data=#
    首先,为什么要保存 migrations 在项目中?
    也许你会说:为什么不在 Python / Django 的项目中 GIT-ignore 所有的 migrations,让每个开发者创建自己的 migration 文件?这样做可以避免掉一些不必要的操作。很好,这就是写这篇文章的一个理由。

    在继续之前,我希望你把在每次改变 model 改变后生成的 migrations 提交并推送到你仓库。这样所有的开发者都会拥有一份相同的 migrations。我必须强调这一点。

    为什么这是如此重要的?想象一下,如果没有 migrations 在你的项目中,团队里的每个成员都要在本地生成自己的 migrations 文件。然而,我的项目最终总会在产品环境下,部署的时候会创建初始化的 migration 同时还会 migrate 数据库。在之后的时间,如果 model 改变我还会重新部署一次,这样又会在产品服务器上生成新的 migration。 但是如果现在发生一些事情,难道我还要有第二台产品服务器?再次部署,创建新的 migration 文件然后 migrate 我的数据库。这样一来,第一台产品服务器就有两份 migration 文件,然而第二台产品服务器只有一份 migration 文件,这一个巨大矛盾。我不能截断任何数据库的改变和执行数据库回滚。从根本上来说,如果你想回滚数据库,那就只能在每个服务器上。

    所以,请保证 migrations 在你的项目中。你也许会遭遇冲突,但是如果你想要你的数据库版本,活着想要回滚数据库,在你的生活中,做一个开发者比监测 migrations 容易的多。

    Migration 冲突
    假设我们有一个 Django 的项目,一份初始化 migration,同时也使用 GIT。我们使用 GIT,所以我们使用分支。我们使用分支,所以在 并分支的时候可能有 migrations 的冲突。当然,在团队中应该知道每个人在做什么,避免修改相同的 models。团队合作是重要的,但是一个人不可能总是避免 migrations 的冲突。因此千万别吓坏了,然后删除数据库,我就是这样干了很多次。它们是可以被很简单的修复,为了做到这一点,我将会解释一些简单的例子,但是它们是很有用的方法。你可以在你需求上选择一个最好的。

    我们需要一份数据库的初始化 migration(Django 将会比较任何一个 model 去初始化 migration,而不是当前的数据库状态),我们不需要手动的修改数据库。

    假设,我们有一个 UserProfile 的 model 同时还有两个分支:

    分支1,一个开发者添加一个 “address” 的字段到 UserProfile Model 中,这样就有了 “migration 0003_userprofile_address.py”
    分支2,我想添加一个 “age” 字段到 UserProfile Model 中,这样就有了 “0003_userprofile_age.py”
    我的分支是分支2,我想合并分支1到分支2,在执行 GIT merge 后,在分支2中不但有我的 migrations 还有从分支1中来的 “0003_userprofile_address.py”。那么问题来了,这两个 migration 文件都试图修改相同的 model,而且都是以 “0003_” 命名的。

    这里有三种可用的解决方法。前面两种是我推荐的,但是劝告你最好避免是使用第三种方法。

    方法1:使用 -merge
    无论何时,在你使用这个方法之前,这都是非常容易的,因为 Django 会自动合并。因此,如果你是有经验丰富的开发者,你事先会知道这种方法是会失败的。考虑到这个选项只对非常简单的 model 的变化非常有用。

    那么,为了让 Django 合并你的 migrations,你应该遵循以下步骤:

    尝试执行 python manage.py migrate (在这个时候,Django 将会查看这些冲突,然后告诉你执行 python manage.py makemigrations –merge
    执行 python manage.py makemigrations –merge,migrations 将会自动被合并;你将会创建一个新的 migration 叫 0004_merge.py 被放在migrations 文件夹中。
    执行 python manage.py migrate
    $ python manage.py migrate
    CommandError: Conflicting migrations detected (0003_userprofile_age, 0003_userprofile_address in myapp).
    To fix them run ‘python manage.py makemigrations --merge’
    $ python manage.py makemigrations --merge
    Merging berguiapp
    Branch 0003_userprofile_age
    - Add field age to userprofile
    Branch 0003_userprofile_address
    - Add field address to userprofile

    Merging will only work if the operations printed above do not conflict
    with each other (working on different fields or models)
    Do you want to merge these migration branches? [y/N] y

    Created new merge migration …/migrations/0004_merge.py
    $ python manage.py migrate
    Operations to perform:
    Synchronize unmigrated apps: …
    Apply all migrations: … myapp, …
    Synchronizing apps without migrations:
    Creating tables…
    Installing custom SQL…
    Installing indexes…
    Running migrations:
    Applying myapp.0003_userprofile_age… OK
    Applying myapp.0003_userprofile_address… OK
    Applying myapp.0004_merge… OK
    $
    请记住这条信息 “Merging will only work if the operations printed above do not conflict with each other (working on different fields or models)”。如果有复杂的修改,那么Django的可能不会正确合并 migrations,你将需要使用另一种方法。

    方法2:回滚然后再次合并
    若果是第一次失败,你应该选择这个方法,或者你不认同有这么多的 migration 文件在你应用程序中。(尽管 Django 允许多个 migration 文件在你的项目中)。

    使用 python manage.py migrate myapp my_most_recent_common_migration 在你的分支中回滚最近正常的 migration。
    你也可以这么做:
    暂时移除你的 migration,执行 python manage.py migrate,再次添加你的 migration 然后执行 python manage.py migrate。如果你的 migrations 涉及到不同的 models,同时又要有不同的 migration 生成,你应该使用这个 case。
    移除这两部分 migrations 同时执行 python manage.py makemigrations 和 python manage.py migrate 获得一个从 0003_userprofile_age.py 和 0003_userprofile_address.py 融合后的 migration。如果你想当前的改变只生成一个 migration, 同时只涉及到相同的 model,你应该使用这个 case。需要注意的是,如果这个 migration 在别的分支中也删除了,确保没有人拥有它和任何人都知道这个已经被删除。如果你删除了,同时有有人使用了,这会导致一些恶心的 BUG。应该遵循一个基本的原装:不要删除后者修改其他人使用的 migration。
    把 migration “0003_“ 改成 “0004_“(这不是强制的,但是得可以这么做),修改依赖属性指向 “0003_” migration 同时执行 python manage.py migrate。这个方案可以替代第一种方案,但是你不得不手动修改 migration 的依赖属性指向最新的一个。你更喜欢回滚然后重新创建 migration 或者你喜欢手动修改 migration ,这都带有浓重的个人色彩。就我个人而言我喜欢第一个。
    执行下面这个 snippet 之前,我移除两个 migrations (考虑到这两个分支都是我创建并且没有别人使用,因此我也使用第二种方法解释以上的东西)

    $ python manage.py migrate myapp 0002_auto_20160316_0909
    Operations to perform:
    Target specific migration: 0002_auto_20160316_0909, from myapp
    Running migrations:
    Unapplying myapp.0003_userprofile_age… OK
    $ python manage.py makemigrations
    Migrations for ‘myapp’:
    0003_auto_20160318_1345.py:
    - Add field address to userprofile
    - Add field age to userprofile
    $ python manage.py migrate
    Operations to perform:
    Synchronize unmigrated apps: …
    Apply all migrations: … myapp, …
    Synchronizing apps without migrations:
    Creating tables…
    Installing custom SQL…
    Installing indexes…
    Running migrations:
    Applying myapp.0003_auto_20160318_1345… OK

    如果有来自分支1的 migration 在相同的地方做和修改,你应该要小心地决定哪些是需要保留的,然后重新 migration。

    方法3: 手动修改 migrations
    这种情况是极少发生的,但是如果你真的到了无法选择的地步,阅读 Django 中 writing Django migrations 的文档(英文 中文),可以让你快速熟悉 migration 的主要部分。

    数据迁移
    在一个项目中其中一个迁移必定是数据迁移。假如有那么一个需求,把一个 ManyToMany 的关系改变成 OneToMany 的关系或者要报一个表分成两个表,这样必然有生成一个 migration。但是数据发生了什么?我们仍然需要数据在当前的数据库中。这就体现了数据迁移带来的好处,你要写一个自定义的 migration,这些脚本会把在执行 python manage.py migrate 之后的表结构和你的数据关联起来。你数据将会在新的表中。

    需要明确你的数据迁移需要依赖什么。这个依赖会涉及到最后生成的 migration (名字,或者更精确的),同时需要被开发者指定。但是如果我们在产品服务器中有不同的 migration 设定,需要在每台服务器上小心地做出相应地依赖设定。虽然这是无趣的,但是可以避免复杂的迁移机制。

    在 fixture 和数据迁移中还是有一些不同。Fixtures 是导入一些默认的数据到数据库中,然而数据迁移是在数据库上改变一些数据。fixture 是一个放在 fixture 文件夹中的一个 JSON 文件,使用命令:python manage.py laoddata myapp/fixtures/my_fixture.json 导入。这种方法是把默认的一类对象放入数据库中。另一种方法是,在 migrations 的文件夹中的数据迁移是一个 migration 文件。你不能使用数据迁移添加新的条目到你的数据库中,你只能在数据库众包修改他们。

    结束
    migrations 是一种很有用的数据库更新机制。当你使用 Django 和数据库工作时候,你必须考虑使用 migrations。

    即使你不是一个后端程序员,或者你使用不同的框架,没有使用类似的机制,尝试去理解他们背后的逻辑。他们也许就不是你第一看见的那么复杂,所有的问题都可以被很好的解决。

    展开全文
  • Django使用心得(一) 善用migrations

    千次阅读 2018-12-18 03:38:03
    在使用和学习Django框架时,发现很多人包括我自己在对Django项目进行版本管理时,通常把migrations文件添加到了.gitignore中。笔者也一直有疑问这种做法是否正确,于是去查看官方文档,找到以下这段。原文:You ...


    在使用和学习Django框架时,发现很多人包括我自己在对Django项目进行版本管理时,通常把migrations文件添加到了.gitignore中。

    笔者也一直有疑问这种做法是否正确,于是去查看官方文档,找到以下这段。

    原文:

    You should think of migrations as a version control system for your database schema. makemigrations is responsible for packaging up your model changes into individual migration files - analogous to commits - and migrate is responsible for applying those to your database.

    The migration files for each app live in a “migrations” directory inside of that app, and are designed to be committed to, and distributed as part of, its codebase. You should be making them once on your development machine and then running the same migrations on your colleagues’ machines, your staging machines, and eventually your production machines.

    中文翻译:

    你可以想象 migrations 相当一个你的数据库的一个版本控制系统。makemigrations 命令负责保存你的模型变化到一个迁移文件 - 和 commits 很类似 - 同时 migrate负责将改变提交到数据库。

    每个 app 的迁移文件会保存到每个相应 app 的“migrations”文件夹里面,并且准备如何去执行它, 作为一个分布式代码库。 每当在你的开发机器或是你同事的机器并且最终在你的生产机器上运行同样的迁移,你应当再创建这些文件。

    根据官方文档的说法,不将migrations提交到仓库的做法时错误的。

    而且如果要使用django自带的封装好的TestCase进行单元测试,migrations也必须保留。

    下一篇文章笔者也会介绍一下django中的TestCase的使用心得。

    下面介绍一下,在项目中migrations的一些使用心得和遇到的一些问题。

    利用migrations初始化数据

    我们现在有一个Book的模型,我想在migrate之后初始化一些数据。

    make_good_use_of_migrations/models.py view raw
    class Book(models.Model):
        name = models.CharField(max_length=32)复制代码

    例如:生成三本名称分别为HamletTempestThe Little Prince的书。

    在执行了python manage.py makemigrations之后migrations文件夹会生成0001_initial.py的文件。

    文件中包含了Book这个模型初始化的一些代码。

    在介绍如何利用migrations初始化数据时,先介绍一下migrations常用的两个操作:

    RunSQLRunPython

    顾名思义分别是执行SQL语句Python函数

    下面我用migrations中的RunPython来初始化数据。

    1. 在相应app下的migrations文件新建0002_init_book_data.py migrations/.
      ​ ├── 0001_initial.py.
      ​ └── 0002_init_book_data.py.

    2. 然后增加Migration类继承django.db.migrations.Migration,并在operations中增加需要执行的代码。

    make_good_use_of_migrations/migrations/0002_init_book_data.py view raw
    from django.db import migrations
    
    """
    make_good_use_of_migrations 是App的名字
    """
    
    
    def init_book_data(apps, schema_editor):
        Book = apps.get_model('make_good_use_of_migrations', 'Book')
        init_data = ['Hamlet', 'Tempest', 'The Little Prince']
        for name in init_data:
            book = Book(name=name)
            book.save()
    
    
    class Migration(migrations.Migration):
        dependencies = [
            ('make_good_use_of_migrations', '0001_initial'),
        ]
    
        # 这里要注意dependencies为上一次migrations的文件名称
    
        operations = [
            migrations.RunPython(init_book_data)
        ]复制代码
    1. 运行python manage.py migrate,可以看到数据已经在数据库中生成了。

    利用migrations修复数据

    我们常常遇到这种情况,例如我需要给Book模型增加一个外键字段,而且这个字段不能为空,所以旧的数据就要进行处理修复,我们可以这样处理。

    1. 先将需要增加的字段null属性设置为True,然后执行makemigrations
    make_good_use_of_migrations/models.py view raw
    class Author(models.Model):
        name = models.CharField(max_length=32)
    
    
    class Book(models.Model):
        name = models.CharField(max_length=32)
        author = models.ForeignKey(to=Author, on_delete=models.CASCADE, null=False)复制代码
    1. 在相应app下的migrations文件新建0004_fix_book_data.py migrations/.
      ├── 0001_initial.py.
      ├── 0002_init_book_data.py.
      ├── 0003_auto_20181204_0533.py.
      └── 0004_fix_book_data.py.
    make_good_use_of_migrations/migrations/0004_fix_book_data.py view raw
    from django.db import migrations
    
    
    def fix_book_data(apps, schema_editor):
        Book = apps.get_model('make_good_use_of_migrations', 'Book')
        Author = apps.get_model('make_good_use_of_migrations', 'Author')
        for book in Book.objects.all():
            author, _ = Author.objects.get_or_create(name='%s author' % book.name)
            book.author = author
            book.save()
    
    
    class Migration(migrations.Migration):
        dependencies = [
            ('make_good_use_of_migrations', '0003_auto_20181204_0533'),
        ]
    
        operations = [
            migrations.RunPython(fix_book_data)
        ]复制代码
    1. 最后再将Book模型中的author字段属性null设为False,并执行makemigrations。执行后会出现,

      You are trying to change the nullable field 'author' on book to non-nullable without a default; we can't do that (the database needs something to populate existing rows).
      Please select a fix:
       1) Provide a one-off default now (will be set on all existing rows with a null value for this column)
       2) Ignore for now, and let me handle existing rows with NULL myself (e.g. because you added a RunPython or RunSQL operation to handle NULL values in a previous data migration)
       3) Quit, and let me add a default in models.py
      Select an option:
      复制代码

      这里选择第2项,意思是忽略该字段已经为空的数据,使用RunPython或者RunSQL自行处理。

      选择完成后在执行python manage.py migrate,会发现数据库中的数据会按照我们的预期处理完成。

    解决多人开发时migrations产生的冲突

    为了模拟多人多分支开发,新建一个master-2的分支,并且版本在创建Author类之前,并且在Book模型中增加remark字段。

    model.py文件中的内容如下:

    make_good_use_of_migrations/models.py view raw
    class Book(models.Model):
        name = models.CharField(max_length=32)
        remark = models.CharField(max_length=32, null=True)复制代码

    migrations文件目录如下:

    migrations/.
    ├── 0001_initial.py.
    ├── 0002_init_book_data.py.
    └──0003_book_remark.py.

    当我们把master-2的代码合并到master时,会发现migrations中出现了重复的编号0003并且他们共同依赖于0002_init_book_data

    migrations/.
    ├── 0001_initial.py.
    ├── 0002_init_book_data.py.
    ├── 0003_auto_20181204_0533.py
    ├── 0003_book_remark.py
    ├── 0004_fix_book_data.py
    └──0005_auto_20181204_0610.py.

    这时候就需要用到命令:

    python manage.py makemigrations --merge
    复制代码

    然后就会在migrations目录生成一个0006_merge_20181204_0622.py文件

    make_good_use_of_migrations/migrations/0006_merge_20181204_0622.py view raw
    from django.db import migrations
    
    class Migration(migrations.Migration):
    
        dependencies = [
            ('make_good_use_of_migrations', '0005_auto_20181204_0610'),
            ('make_good_use_of_migrations', '0003_book_remark'),
        ]
    
        operations = [
        ]复制代码

    这时候在执行python manage.py migrate就可以了。

    使用migrations.RunPython需要注意的问题

    在函数中是无法调用模型类的函数的

    假设在Book模型中定义了两个函数print_name和类函数print_class_name

    make_good_use_of_migrations/models.py view raw
    class Book(models.Model):
        name = models.CharField(max_length=32)
        author = models.ForeignKey(to=Author, on_delete=models.CASCADE, null=False)
        remark = models.CharField(max_length=32, null=True)
    
        def print_name(self):
            print(self.name)
    
        @classmethod
        def print_class_name(cls):
            print(cls.__name__)复制代码

    migrations中是无法调用的,笔者也没有仔细研究,推测是Book类初始化时只把字段初始化了。

    make_good_use_of_migrations/migrations/0004_fix_book_data.py view raw
    from django.db import migrations
    
    
    def fix_book_data(apps, schema_editor):
        Book = apps.get_model('make_good_use_of_migrations', 'Book')
        Author = apps.get_model('make_good_use_of_migrations', 'Author')
        for book in Book.objects.all():
            author, _ = Author.objects.get_or_create(name='%s author' % book.name)
            book.author = author
            """
            book.print_name()
            book.print_class_name()
            这样调用会报错
            """
            book.save()
    
    
    class Migration(migrations.Migration):
        dependencies = [
            ('make_good_use_of_migrations', '0003_auto_20181204_0533'),
        ]
    
        operations = [
            migrations.RunPython(fix_book_data)
        ]复制代码

    在函数中模型的类所重写的save方法无效,包括继承的save方法

    migrations中所有重写的save方法都不会运行,例如:

    make_good_use_of_migrations/models.py view raw
    class Book(models.Model):
        name = models.CharField(max_length=32)
        author = models.ForeignKey(to=Author, on_delete=models.CASCADE, null=False)
        remark = models.CharField(max_length=32, null=True)
    
        def print_name(self):
            print(self.name)
    
        @classmethod
        def print_class_name(cls):
            print(cls.__name__)
    
        def save(self, *args, **kwargs):
            if not self.remark:
                self.remark = 'This is a book.'复制代码

    最后初始化生成的数据的remark字段的值仍然为空。

    在函数中模型注册的所有signal无效

    虽然给Book模型注册了signal,但是在migrations中仍然不会起作用

    make_good_use_of_migrations/models.py view raw
    @receiver(pre_save, sender=Book)
    def generate_book_remark(sender, instance, *args, **kwargs):
        print(instance)
        if not instance.remark:
            instance.remark = 'This is a book.'复制代码

    不要将数据处理放到模型变更的migrations文件中

    在做数据修复或者生成初始化数据时,不要将处理函数放到自动生成的变更或生成字段、模型的migrations文件中,例如:

    make_good_use_of_migrations/migrations/0005_auto_20181204_0610.py view raw
    class Migration(migrations.Migration):
        dependencies = [
            ('make_good_use_of_migrations', '0004_fix_book_data'),
        ]
    
        operations = [
            migrations.AlterField(
                model_name='book',
                name='author',
                field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE,
                                        to='make_good_use_of_migrations.Author'),
            ),
            """
            migrations.RunPython(xxx) 不要把数据处理放到模型变更中
            """
        ]复制代码

    不要放在一起的主要原因是,当RunPython中函数的处理逻辑一旦出现异常无法向下执行,

    django_migrations将不会记录这一次处理,但是表结构的变更已经执行了!

    这也是Django migrations做的不好的地方,正确应该是出现异常需要做数据库回滚。

    一旦出现这种情况,只能手动将migrations的名称如0005_auto_20181204_0610,写入到数据库表django_migrations中,然后将RunPython中的逻辑单独剥离出来。

    总结

    以上就是笔者在项目中使用Django框架的migrations的心得,下一篇会介绍Django框架的TestCase

    本文的源码会放到github上,github.com/elfgzp/djan…

    本人博客原文地址:elfgzp.cn/2018/12/04/…


    展开全文
  • 有一道关于python-django开发工程师的面试题: 内容大致是makemigrations 和 migrate 工作原理分别是什么, 如果不想使用 Django 的 makemigrations 和 migrate 功能,但是不小心执行了这两个命令会发生什么, ...
  • Django的migrations机制概述

    千次阅读 2017-09-28 12:50:36
    Django框架提供的migrations是一个独立的机制,主要用以在Django应用中的model类和数据库结构的schema之间进行同步。 1. Django应用中的model类 model是业务逻辑的数据对象,包含fields和behaviors。 一种model类...
  • 有一道关于python-django开发工程师的面试题: 内容大致是makemigrations 和 migrate 工作原理分别是什么, 如果不想使用 Django 的 makemigrations 和 migrate 功能,但是不小心执行了这两个命令会发生什么, ...
  • migrations

    2016-05-31 22:31:00
    Run migrations Run EntityFramework migrations to create database schema for blog module. To run migrations from command line, we first create an empty folder, copy all files from "packages\EntityFra...
  • 以太坊:合约部署(Migrations

    万次阅读 2019-05-09 09:16:37
    合约部署(Migrations) 注解 译者注:Migrations 直译”迁移“,当作为一个名词时,有时指的是用来部署的脚本文件,称之为迁移文件,作为动词会翻译成部署,请读者了解。 迁移脚本(JavaScript文件)可帮助我们...
  • C# EF codefirst 迁移 Migrations

    千次阅读 2018-11-07 10:23:53
    迁移 Migrations 创建初始模型和数据库——使用Migrations前的准备  在开始使用迁移(Migrations)之前,我们需要一个Project和一个Code First Model, 对于本文将使用典型的Blog和Post模型 创建一个新的...
  • 1.Doctrine Migrations是什么? 团队开发中,每个开发人员对于数据库都修改都必须手动记录,上线时需要人工整理,运维成本极高。而且在多个开发者之间数据结构同步也是很大的问题。Doctrine Migrations组件把数据库...
  • 官网:http://mybatis.org/migrations/ 网络:http://blog.csdn.net/daquan198163/article/details/9284611 http://wenku.baidu.com/view/0b2e4801a8114431b90dd83b.html 安装: https://code.google.com/p/
  •  删除该app名字下的migrations下的__init__.py等文件。 第二步:  进入数据库,找到django_migrations的表,删除该app名字的所有记录。 第三步:执行下面这两条命令:(在项目目录下) python manage.py ...
  • django migrations

    2018-06-15 11:45:41
    django migrations转载:https://blog.csdn.net/jazywoo123/article/details/49821051在1.6之前, Django只支持添加新的model到数据库, 而无法编辑或修改已经存在的model. 在当时, 这些Django缺失的功能可以通过South...
  • dotnet ef migrations add <name of migration> [Package Manager console] add-migration <name of migration> 创建迁移时,EF会将模型的当前状态与先前的迁移(如果存在)进行比较,并生成一个文件....
  • django项目中迁移表时 报了这么一个错误 ...第一步 找到app下的migrations文件夹 第二步 删除文件夹下的文件 init.py 不要删除 第三步 把你mysql数据库中 django表删除 最后 再重新迁移 就完成了 ...
  • 在开发过程中,由于需求变更或者自我重构,需要清理migrations,以保持代码整洁和后续的可维护性。 场景一 不考虑数据库数据表,可以完全清空数据库里面的表的数据。 步骤: 删除所有migrations find . -path "/...
  • To enable migrations for 'MVCAndEF.Models.MVCopenEntities', use Enable-Migrations -ContextTypeName MVCAndEF.Models.MVCopenEntities. To enable migrations for 'MVCAndEF.Models.MVCAndEFContext', use ...
  • 在进行django开发的时候,遇到这样的情况,在models文件进行了新增表或修改表,删除了migrations,再生成新的migrations后进行migrate,会出现以下提示: 1 2 3 4 5 Operations to perform: Apply all migrations: ...
  • 1、EF Code First创建数据库  新建控制台应用程序Portal,通过程序包管理器控制台添加EntityFramework。  在程序包管理器控制台中执行以下语句,安装EntityFramework。 ... Install-Package EntityFrame...

空空如也

1 2 3 4 5 ... 20
收藏数 22,977
精华内容 9,190
关键字:

migrations