我如何使用bulkuploader使用db.SelfReferenceProperty填充类? [英] How can I use bulkuploader to populate class with a db.SelfReferenceProperty?
问题描述
我有一个使用 csv(...) db.SelfReferenceProperty
创建树状结构的类。使用 appcfg.py upload_data - config_file = bulkloader.yaml --kind = Group --filename = group尝试填充数据库时尝试使用
,我收到一个异常说 BadValueError:name不能为空
。 (Full stack below)
我尝试订购数据以确保外键指向它的组是第一个。这是行不通的。
通过从bulkloader.yaml中进行转换的线import_transform:transform.create_foreign_key('Group'),数据被上传,但它将该属性存储为字符串,打破了我的应用程序逻辑。
- kind:Group
connector:csv
connector_options:
property_map:
- 属性:__key__ $ b $ external_name:key
export_transform:transform.key_id_or_name_as_string
$ b $ - 属性:name
external_name:name
#类型:String Stats:这种类型的9种属性。
- 属性:section
external_name:section
#类型:Key Stats:此类型的6个属性。
import_transform:transform.create_foreign_key('Group')
export_transform:transform.key_id_or_name_as_string
<有没有什么办法可以让批量加载程序考虑自引用,还是应该对批量加载的数据进行转换,或者实现我自己的批量加载算法?
----
Traceback(最近一次调用最后一次):
文件/home/username/src/google_appengine/google/appengine/tools/adaptive_thread_pool.py第150行,在WorkOnItems
status,instruction = item.PerformWork(self .__ thread_pool)
文件/home/username/src/google_appengine/google/appengine/tools/bulkloader.py,第691行,在PerformWork
transfer_time = self._TransferItem(thread_pool)
文件/home/username/src/google_appengine/google/appengine/tools/bulkloader.py,行846,在_TransferItem
self.content = self.request_manager.EncodeContent(self.rows)
文件/ home / u / home /父/母/母/母)
实体= loader.create_entity($ key $ key $ key $ parent $ parent $ parent $ parent $ parent $ parent $ parent $ appengine / tools / bulkloader.py) /username/src/google_appengine/google/appengine/ext/bulkload/bulkloader_config.py,第382行,在create_entity
返回self.dict_to_entity(input_dict,self.bulkload_state)
文件/ home / username / home / username / src / bin目录下的/ bs / google_appengine / google / appengine / ext / bulkload / bulkloader_config.py,第230行,在__run_import_transforms
value = self .__ dict_to_prop(transform,input_dict,bulkload_state)
文件/ home / username / src / google_appengine /google/appengine/ext/bulkload/bulkloader_config.py,第188行,位于__dict_to_prop
value = transform.import_transform(value)
文件/ home / user名称/ src / google_appengine / google / appengine / ext / bulkload / bulkloader_parser.py,第93行,在__call__
返回self.method(* args,** kwargs)
文件/ home / username /src/google_appengine/google/appengine/ext/bulkload/transform.py,行114,在generate_foreign_key_lambda
返回datastore.Key.from_path(kind,value)
文件/ home / username / src / home / username / src / google_appengine / google / appengine / google_appengine / api / datastore_types.py,第109行,在ValidateString
引发异常('%s不能为空。'%name)
BadValueError:名称不能为空。
helpers.py
文件来成功解决此问题,以充当 transform.create_foreign_key code>: from google.appengine.api导入数据存储区
def create_foreign_key(kind ,key_is_id = False):
def generate_foreign_key_lambda(value):
如果value是None:
return None
如果key_is_id:
value = int(值)
尝试:
返回datastore.Key.from_path(类型,值)
除外:
返回无
返回generate_foreign_key_lambda
一旦该文件与yaml bolk上传配置文件( bulkloader .yaml
),您将其添加到该文件中:
python_preamble:
- ( ...)
- 导入:助手
变形金刚:
$ b $ - 种类:Group
连接器:csv
connector_options:
property_map:
- property:__key__
external_name:key
export_transform:transform.key_id_or_name_as_string
- property:name
external_name:name
- property:section
external_name:section
import_transform:helpers.create_foreign_key('Group')
#^^^^^^^我们使用包装来代替
export_transform:transform.key_id_or_name_as_string
通过这些更改,现在批量上传功能正常运行。
在使用这个之前,你应该修改所有的,除了
,并且可以替换为 BadValueError
。
I've got a class that is using db.SelfReferenceProperty
to create a tree-like structure.
When trying to populate the database using appcfg.py upload_data -- config_file=bulkloader.yaml --kind=Group --filename=group.csv (...)
, I'm getting an exception saying BadValueError: name must not be empty
. (Full stack below)
I tried ordering the data to make sure that a Groups that had a foreign key pointing at them were first. That didn't work.
By commenting from the bulkloader.yaml the line making the transformation "import_transform: transform.create_foreign_key('Group')", the data is uploaded, but it stores that property as string, breaking my application logic.
- kind: Group
connector: csv
connector_options:
property_map:
- property: __key__
external_name: key
export_transform: transform.key_id_or_name_as_string
- property: name
external_name: name
# Type: String Stats: 9 properties of this type in this kind.
- property: section
external_name: section
# Type: Key Stats: 6 properties of this type in this kind.
import_transform: transform.create_foreign_key('Group')
export_transform: transform.key_id_or_name_as_string
Is there any way to make the bulkloader take into account selfreferences, or should I either make a transformation serverside of the bulkloaded data or implement my own bulk loading algorithm?
----
Traceback (most recent call last):
File "/home/username/src/google_appengine/google/appengine/tools/adaptive_thread_pool.py", line 150, in WorkOnItems
status, instruction = item.PerformWork(self.__thread_pool)
File "/home/username/src/google_appengine/google/appengine/tools/bulkloader.py", line 691, in PerformWork
transfer_time = self._TransferItem(thread_pool)
File "/home/username/src/google_appengine/google/appengine/tools/bulkloader.py", line 846, in _TransferItem
self.content = self.request_manager.EncodeContent(self.rows)
File "/home/username/src/google_appengine/google/appengine/tools/bulkloader.py", line 1267, in EncodeContent
entity = loader.create_entity(values, key_name=key, parent=parent)
File "/home/username/src/google_appengine/google/appengine/ext/bulkload/bulkloader_config.py", line 382, in create_entity
return self.dict_to_entity(input_dict, self.bulkload_state)
File "/home/username/src/google_appengine/google/appengine/ext/bulkload/bulkloader_config.py", line 133, in dict_to_entity
self.__run_import_transforms(input_dict, instance, bulkload_state_copy)
File "/home/username/src/google_appengine/google/appengine/ext/bulkload/bulkloader_config.py", line 230, in __run_import_transforms
value = self.__dict_to_prop(transform, input_dict, bulkload_state)
File "/home/username/src/google_appengine/google/appengine/ext/bulkload/bulkloader_config.py", line 188, in __dict_to_prop
value = transform.import_transform(value)
File "/home/username/src/google_appengine/google/appengine/ext/bulkload/bulkloader_parser.py", line 93, in __call__
return self.method(*args, **kwargs)
File "/home/username/src/google_appengine/google/appengine/ext/bulkload/transform.py", line 114, in generate_foreign_key_lambda
return datastore.Key.from_path(kind, value)
File "/home/username/src/google_appengine/google/appengine/api/datastore_types.py", line 384, in from_path
ValidateString(id_or_name, 'name')
File "/home/username/src/google_appengine/google/appengine/api/datastore_types.py", line 109, in ValidateString
raise exception('%s must not be empty.' % name)
BadValueError: name must not be empty.
解决方案 Using an answer given to a similar problem as a base, I could successfully solve this by creating a small helpers.py
file to do act as a wrapper around transform.create_foreign_key
:
from google.appengine.api import datastore
def create_foreign_key(kind, key_is_id=False):
def generate_foreign_key_lambda(value):
if value is None:
return None
if key_is_id:
value = int(value)
try:
return datastore.Key.from_path(kind, value)
except:
return None
return generate_foreign_key_lambda
Once that file is in place in the same directory as your yaml bolk upload configuration file (bulkloader.yaml
), you add this to that file:
python_preamble:
- (...)
- import: helpers
transformers:
- kind: Group
connector: csv
connector_options:
property_map:
- property: __key__
external_name: key
export_transform: transform.key_id_or_name_as_string
- property: name
external_name: name
- property: section
external_name: section
import_transform: helpers.create_foreign_key('Group')
# ^^^^^^^ we use the wrapper instead
export_transform: transform.key_id_or_name_as_string
With those changes, the bulk upload is now working correctly.
Before using this, you should definitely modify the catch all except
, and replace it with may be except BadValueError
.
这篇关于我如何使用bulkuploader使用db.SelfReferenceProperty填充类?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!