zoukankan      html  css  js  c++  java
  • makemigrations 和 migrate工作原理分别是什么

    有一道关于python-django开发工程师的面试题:

    • 内容大致是makemigrations 和 migrate 工作原理分别是什么,
    • 如果不想使用 Django 的 makemigrations 和 migrate 功能,但是不小心执行了这两个命令会发生什么,
    • 如何禁用 migrate 的功能。

    下面我们来分析一下这几个问题。

    首先:
    manage.py是每个django项目中自动生成的一个用于管理项目的脚本文件。需要通过python命令执行。manage.py接受的是Django提供的内置命令。

    内置命令包含:

    • check
    • makemigrations
    • migrate
    • runserver
    • startapp
    • startproject
    • 还有其他的我先不写了,这是比较常用的
    • 本篇文章主要根据题目分析makemigrations和migrate

    makemigrations:

    • 根据检测到的模型创建新的迁移。迁移的作用,更多的是将数据库的操作,以文件的形式记录下来,方便以后检查、调用、重做等等。

    有这样一道很熟悉的命令:

    python manger.py makemigrations
    

    相当于在该app下建立 migrations目录,并记录下你所有的关于modes.py的改动,比如0001_initial.py。
    但是 这个改动还没有作用到数据库文件
    在这里插入图片描述

    个人白话翻译:也就是说你改了models的时候,你就得删了0001这个日志文件,然后删库重来 python manage.py makemigrations 创建新的迁移

    migrate:

    • 使数据库状态与当前模型集和迁移集同步。说白了,就是将对数据库的更改,主要是数据表设计的更改,在数据库中真实执行。例如,新建、修改、删除数据表,新增、修改、删除某数据表内的字段等等。

    个人白话翻译:你改了models的时候,数据库也会真实的执行。

    在python manger.py makemigrations之后执行命令:

    python manager.py migrate
    
    • 1

    就将该改动作用到数据库文件

    如何禁用migrate的功能:

    Django < 1.9版本时

    from settings import *
    class DisableMigrations(object):
        def __contains__(self, item):
            return True
        def __getitem__(self, item):
            return 'notmigrations'
    MIGRATION_MODULES = DisableMigrations()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    Django >= 1.9版本时
    有这么一个配置项目 MIGRATION_MODULES。

    from settings import *
    MIGRATION_MODULES = {
        'auth': None,
        'contenttypes': None,
        'default': None,
        'sessions': None,
        'core': None,
        'profiles': None,
        'snippets': None,
        'scaffold_templates': None,
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    其他Django版本:

    SOUTH_TESTS_MIGRATE = False
    
    • 1

    基于元类设计的makemigrations和migrate

    makemigrations和migrate是两条基于元类设计的Django ORM数据库命令

    python的元类:

    元类就是用来创建类的“东西”。你创建类就是为了创建类的实例对象。
    元类就是用来创建这些类(对象)的,元类就是类的类

    基于django-ORM的元类

    ORM:对象关系映射.
    用于实现面向对象编程语言里不同类型系统的数据之间的转换 。从效果上说,它其实是创建了一个可在编程语言里使用的“虚拟对象数据库”。
    其本质是通过调用对象实现同等的sql语句

    我们来看下面代码:

    class Field(object):
        def __init__(self,name,column_tyoe):
            self.name = name
            self.column_type = column_tyoe
        def __str__(self):
            return '&lt;%s:%s&gt;'%(self.__class__.__name__,self.name)
    
    class StringField(Field):
        def __init__(self,name):
            super(StringField,self).__init__(name,"varchar(100)")
    
    class IntegerField(Field):
        def __init__(self,name):
            super(IntegerField,self).__init__(name,"bigint")
    
    class ModelMetaClass(type):
        def __new__(cls, name,bases,attrs):
            if name == "Model":
                return type.__new__(cls,name,bases,attrs)
            print('found model:%s'%name)
            mapping = dict()
            for k,v in attrs.items():
                if isinstance(v,Field):
                    print("Found mapping:%s ==&gt;%s"%(k,v))
                    mapping[k] = v
            for k in mapping.keys():
                attrs.pop(k)
            attrs['__mappings__'] = mapping
            attrs['__table__'] = name
            return type.__new__(cls,name,bases,attrs)
    
    class Model(dict,metaclass = ModelMetaClass):
        def __init__(self,**kwargs):
            super(Model,self).__init__(**kwargs)
        def __getattr__(self, key):
            try:
                return self[key]
            except KeyError:
                raise AttributeError("Module objects has no attribute %s"%key)
        def __setattr__(self, key, value):
            self[key] = value
    
        def save(self):
            fields = []
            args = []
            for k,v in self.__mappings__.items():
                fields.append(v.name)
                args.append(getattr(self,k,None))
            sql = 'insert into %s (%s) values (%s)'%(self.__table__,",".join(fields),",".join(str(i) for i in args))
            print("SQL:%s"%sql)
            print("ARGS: %s"%str(args))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 1

    class User(Model):
    # 定义类的属性到列的映射:
    id = IntegerField(‘id’)
    name = StringField(‘username’)
    email = StringField(‘email’)
    password = StringField(‘password’)

    u = User(id=12345, name=‘Batman’, email=‘batman@nasa.org’, password=‘iamback’)
    u.save()

    中心思想: 用元类来创建user类,id、name、email、password等属性。传递到元类,元类接受之后把他们转换成字典,用_ _mapings保存,也就是user用__table__保存.

    本篇整合:

    1、makemigrations 和 migrate 工作原理分别是什么:

    • makemigrations:根据检测到的模型创建新的迁移。迁移的作用,更多的是将数据库的操作,以文件的形式记录下来,方便以后检查、调用、重做等等。
    • migrate:使数据库状态与当前模型集和迁移集同步。说白了,就是将对数据库的更改,主要是数据表设计的更改,在数据库中真实执行。例如,新建、修改、删除数据表,新增、修改、删除某数据表内的字段等等。

    2、如果不想使用 Django 的 makemigrations 和 migrate 功能,但是不小心执行了这两个命令会发生什么,

    • 首先在该app下建立 migrations目录,并记录下你所有的关于modes.py的改动,比如0001_initial.py,
    • 接着执行migrate的话,这时候会作用到数据库文件,产生对应的表

    3、如何禁用 migrate 的功能。

    • 详情见文中各版本对应设置。
  • 相关阅读:
    设计模式——适配器模式
    设计模式——模板方法模式
    03-Web开发(上)
    02-配置文件
    01-QuickStart
    34-多线程(下)
    33-IO(下)
    15-后端编译与优化(待补充)
    14-线程安全与锁优化
    13-JUC(下)
  • 原文地址:https://www.cnblogs.com/xin-qing3/p/10875491.html
Copyright © 2011-2022 走看看