在Google App Engine(Python)中将数据从产品数据存储传输到本地开发环境数据存储
TL;DR我需要找到一个真正的解决方案,从产品数据存储中下载数据并将其加载到本地开发环境 具体问题是: 我需要在本地开发服务器上用产品服务器数据存储上的真实数据(不是实时数据)测试我的应用程序。文档和其他资源提供了三种选择:在Google App Engine(Python)中将数据从产品数据存储传输到本地开发环境数据存储,python,google-app-engine,Python,Google App Engine,TL;DR我需要找到一个真正的解决方案,从产品数据存储中下载数据并将其加载到本地开发环境 具体问题是: 我需要在本地开发服务器上用产品服务器数据存储上的真实数据(不是实时数据)测试我的应用程序。文档和其他资源提供了三种选择: 使用从产品服务器下载数据,然后将其加载到本地开发环境中。当我使用这个方法时,由于Oauth问题,我得到了“错误的请求”错误。此外,此方法将被弃用。官方文件建议使用第二种方法: 使用。此方法的epic文档说明了如何备份console(中)上的所有数据。我试过这种方法。备份数据
appcfg.py更新-一个沙盒id
,并使用datastore admin在google云存储中创建生产备份,然后在沙盒中使用datastore admin在沙盒中还原此备份
将生产数据克隆到本地主机
我确实使用一些生产数据来初始化本地主机数据存储,但这不是一个完整的克隆。只有核心所需的对象和一些测试用户
为此,我编写了一个GoogleDataflow作业,导出选定的模型,并以jsonl格式将它们保存在google云存储中。然后在本地主机上,我有一个名为/init/
的端点,它启动taskqueue作业来下载这些导出并导入它们
为此,我重用JSON REST处理程序代码,该代码能够将任何模型转换为JSON,反之亦然
理论上,您可以对整个数据存储区执行此操作
编辑-这是我的to json/from json代码的样子:
myndb.Model
s的所有子类myBaseModel
具有通用转换代码:
get_dto_typemap = {
ndb.DateTimeProperty: dt_to_timestamp,
ndb.KeyProperty: key_to_dto,
ndb.StringProperty: str_to_dto,
ndb.EnumProperty: str,
}
set_from_dto_typemap = {
ndb.DateTimeProperty: timestamp_to_dt,
ndb.KeyProperty: dto_to_key,
ndb.FloatProperty: float_from_dto,
ndb.StringProperty: strip,
ndb.BlobProperty: str,
ndb.IntegerProperty: int,
}
class BaseModel(ndb.Model):
def to_dto(self):
dto = {'key': key_to_dto(self.key)}
for name, obj in self._properties.iteritems():
key = obj._name
value = getattr(self, obj._name)
if obj.__class__ in get_dto_typemap:
if obj._repeated:
value = [get_dto_typemap[obj.__class__](v) for v in value]
else:
value = get_dto_typemap[obj.__class__](value)
dto[key] = value
return dto
def set_from_dto(self, dto):
for name, obj in self._properties.iteritems():
if isinstance(obj, ndb.ComputedProperty):
continue
key = obj._name
if key in dto:
value = dto[key]
if not obj._repeated and obj.__class__ in set_from_dto_typemap:
try:
value = set_from_dto_typemap[obj.__class__](value)
except Exception as e:
raise Exception("Error setting "+self.__class__.__name__+"."+str(key)+" to '"+str(value) + "': " + e.message)
try:
setattr(self, obj._name, value)
except Exception as e:
print dir(obj)
raise Exception("Error setting "+self.__class__.__name__+"."+str(key)+" to '"+str(value)+"': "+e.message)
class User(BaseModel):
# user fields, etc
然后,我的请求处理程序使用set\u from\u dto
&to\u dto
如下(BaseHandler
还提供了一些方便的方法,用于将json有效负载转换为python dict等等):
谢谢“将生产数据克隆到本地主机”可以解决我的问题。我已经从数据存储中编写了一个作为JSON的导出脚本。在本地开发环境中,我开始编写导入脚本,但我不能。您能详细说明JSON REST处理程序逻辑吗?我需要了解的是;我应该为每个模型重写转换代码还是有更简单的方法?我在上面添加了我的代码。我所有的模型都是子类
BaseModel
,所以这一对函数几乎适用于所有模型。在某些型号上,我必须覆盖到_dto
和从_dto设置_
,以对基本型号
的功能进行一些调整
class RestHandler(BaseHandler):
MODEL = None
def put(self, resource_id=None):
if resource_id:
obj = ndb.Key(self.MODEL, urlsafe=resource_id).get()
if obj:
obj.set_from_dto(self.json_body)
obj.put()
return obj.to_dto()
else:
self.abort(422, "Unknown id")
else:
self.abort(405)
def post(self, resource_id=None):
if resource_id:
self.abort(405)
else:
obj = self.MODEL()
obj.set_from_dto(self.json_body)
obj.put()
return obj.to_dto()
def get(self, resource_id=None):
if resource_id:
obj = ndb.Key(self.MODEL, urlsafe=resource_id).get()
if obj:
return obj.to_dto()
else:
self.abort(422, "Unknown id")
else:
cursor_key = self.request.GET.pop('$cursor', None)
limit = max(min(200, self.request.GET.pop('$limit', 200)), 10)
qs = self.MODEL.query()
# ... other code that handles query params
results, next_cursor, more = qs.fetch_page(limit, start_cursor=cursor)
return {
'$cursor': next_cursor.urlsafe() if more else None,
'results': [result.to_dto() for result in results],
}
class UserHandler(RestHandler):
MODEL = User