我如何使用bulkuploader使用db.SelfReferenceProperty填充类? [英] How can I use bulkuploader to populate class with a db.SelfReferenceProperty?

查看:209
本文介绍了我如何使用bulkuploader使用db.SelfReferenceProperty填充类?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个使用 db.SelfReferenceProperty 创建树状结构的类。使用 appcfg.py upload_data - config_file = bulkloader.yaml --kind = Group --filename = group尝试填充数据库时尝试使用

csv(...)
,我收到一个异常说 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:名称不能为空。


解决方案

使用给出类似问题的答案

a>作为基础,我可以通过创建一个小 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆