English 中文(简体)
3. 迁移应用引擎模型的方法
原标题:Method to migrate App Engine models
  • 时间:2009-10-14 15:39:45
  •  标签:

数据库的迁移是一种受欢迎的模式,特别是同Rub有关铁路的数据库。 由于移民具体说明了如何用旧的数据来适应新的图象,如果你掌握必须迅速和可靠地转换的生产数据,那么这种数据会是有益的。

但是,评估引擎的迁移模式是困难的,因为按顺序处理所有实体的工作都很困难,而且没有任何一条大交易中有效迁移所有东西的线性操作。

What are your techniques for modifying a db.Model "schema" and migrating the data to fit the new schema?

最佳回答

我就是这样做的。

我有一个米格米德班,我的所有模式都继承这一班。 这里的移民是:

"""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>>失败,则迁移法应重新计算,如果移徙工作不成重要错误,则可能出现重大错误。

然而,在某个时候,我可能把我的移民从一个单独的档案中混在一起。

Final thoughts

很难对上诉引擎进行测试。 很难在试验环境中获得你的生产数据,此时难以做到一致地重估。 因此,为了进行重大修改,应考虑制作新的版本,使用完全不同的“号”模式,从旧模式进口并按需要迁移。 (例如,User2,而不是User。 这样,如果你需要回到原来的版本,你就会有效地支持数据。

问题回答

暂无回答




相关问题
热门标签