数据库的迁移是一种受欢迎的模式,特别是同Rub有关铁路的数据库。 由于移民具体说明了如何用旧的数据来适应新的图象,如果你掌握必须迅速和可靠地转换的生产数据,那么这种数据会是有益的。
但是,评估引擎的迁移模式是困难的,因为按顺序处理所有实体的工作都很困难,而且没有任何一条大交易中有效迁移所有东西的线性操作。
数据库的迁移是一种受欢迎的模式,特别是同Rub有关铁路的数据库。 由于移民具体说明了如何用旧的数据来适应新的图象,如果你掌握必须迅速和可靠地转换的生产数据,那么这种数据会是有益的。
但是,评估引擎的迁移模式是困难的,因为按顺序处理所有实体的工作都很困难,而且没有任何一条大交易中有效迁移所有东西的线性操作。
我就是这样做的。
我有一个米格米德班,我的所有模式都继承这一班。 这里的移民是:
"""Models which know how to migrate themselves"""
import logging
from google.appengine.ext import db
from google.appengine.api import memcache
class MigrationError(Exception):
"""Error migrating"""
class MigratingModel(db.Model):
"""A model which knows how to migrate itself.
Subclasses must define a class-level migration_version integer attribute.
"""
current_migration_version = db.IntegerProperty(required=True, default=0)
def __init__(self, *args, **kw):
if not kw.get( _from_entity ):
# Assume newly-created entities needn t migrate.
try:
kw.setdefault( current_migration_version ,
self.__class__.migration_version)
except AttributeError:
msg = ( migration_version required for %s
% self.__class__.__name__)
logging.critical(msg)
raise MigrationError, msg
super(MigratingModel, self).__init__(*args, **kw)
@classmethod
def from_entity(cls, *args, **kw):
# From_entity() calls __init__() with _from_entity=True
obj = super(MigratingModel, cls).from_entity(*args, **kw)
return obj.migrate()
def migrate(self):
target_version = self.__class__.migration_version
if self.current_migration_version < target_version:
migrations = range(self.current_migration_version+1, target_version+1)
for self.current_migration_version in migrations:
method_name = migrate_%d % self.current_migration_version
logging.debug( %s migrating to %d: %s
% (self.__class__.__name__,
self.current_migration_version, method_name))
getattr(self, method_name)()
db.put(self)
return self
<代码>Migration Model 拦截了从原始数据储存实体向全方位转售。 示范。 如果当值_migration_version
低于最新类别migration_version
,则使用一系列<代码>_migrate_N(方法,重提。
例如:
"""Migrating model example"""
# ...imports...
class User(MigratingModel):
migration_version = 3
name = db.StringProperty() # deprecated: use first_name and last_name
first_name = db.StringProperty()
last_name = db.StringProperty()
age = db.IntegerProperty()
invalid = db.BooleanProperty() # to search for bad users
def migrate_1(self):
"""Convert the unified name to dedicated first/last properties."""
self.first_name, self.last_name = self.name.split()
def migrate_2(self):
"""Ensure the users names are capitalized."""
self.first_name = self.first_name.capitalize()
self.last_name = self.last_name.capitalize()
def migrate_3(self):
"""Detect invalid accounts"""
if self.age < 0 or self.age > 85:
self.invalid = True
在一个繁忙的地点,如果<条码>db.put(<>/code>>失败,则迁移法应重新计算,如果移徙工作不成重要错误,则可能出现重大错误。
然而,在某个时候,我可能把我的移民从一个单独的档案中混在一起。
很难对上诉引擎进行测试。 很难在试验环境中获得你的生产数据,此时难以做到一致地重估。 因此,为了进行重大修改,应考虑制作新的版本,使用完全不同的“号”模式,从旧模式进口并按需要迁移。 (例如,User2
,而不是User
。 这样,如果你需要回到原来的版本,你就会有效地支持数据。