如何使用bulkuploader 用 db.SelfReferenceProperty 填充类?
我有一个类使用 db.SelfReferenceProperty 来创建树状结构。
尝试使用 appcfg.py upload_data --config_file=bulkloader.yaml --kind=Group --filename=group.csv (...) 填充数据库时 ,我收到一个异常,提示 BadValueError:名称不能为空
。 (下面是完整堆栈)
我尝试对数据进行排序,以确保具有指向它们的外键的组位于第一个。那行不通。
通过从bulkloader.yaml中注释进行转换的行“import_transform:transform.create_foreign_key(‘Group’)”,数据被上传,但它将该属性存储为字符串,破坏了我的应用程序逻辑。
- 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
有没有什么方法可以使批量加载器考虑自引用,或者我应该对批量加载的数据进行服务器端转换或实现我自己的批量加载算法?
----
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.
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
使用对类似问题的回答作为基地,我可以通过创建一个小
helpers.py
文件来成功解决这个问题,作为transform.create_foreign_key
的包装:一旦该文件位于同一目录中作为您的 yaml 批量上传配置文件 (
bulkloader.yaml
),您可以将其添加到该文件中:通过这些更改,批量上传现在可以正常工作了。
在使用这个之前,你一定要修改catch all
except ,并将其替换为may be
except BadValueError 。
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 aroundtransform.create_foreign_key
: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: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 beexcept BadValueError
.transform.py
(也许只是最近)包含一个解决此问题的装饰器:因此使用以下内容也可以解决该问题,而无需引入自定义
helpers.py
文件:transform.py
(maybe only recently) contains a decorator that solves this issue:So using the following will also solve the problem, without the introduction of a custom
helpers.py
file: