有一道关于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 makemigrations 创建新的迁移
migrate:
- 使数据库状态与当前模型集和迁移集同步。说白了,就是将对数据库的更改,主要是数据表设计的更改,在数据库中真实执行。例如,新建、修改、删除数据表,新增、修改、删除某数据表内的字段等等。
个人白话翻译:你改了models的时候,数据库也会真实的执行。
在python 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 '<%s:%s>'%(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 ==>%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 的功能。
- 详情见文中各版本对应设置。