Как я могу использовать bulkuploader для заполнения класса с помощью db.SelfReferenceProperty?

У меня есть класс, который использует db.SelfReferenceProperty для создания древовидной структуры.

При попытке заполнить базу данных с помощью appcfg.py upload_data -- config_file=bulkloader.yaml --kind=Group --filename=group.csv (...) , я получаю исключение, говорящее, что BadValueError: name must not be empty , (Полный стек ниже)

Я попытался упорядочить данные, чтобы убедиться, что группы, у которых был внешний ключ, указывающий на них, были первыми. Это не сработало.

Комментируя из bulkloader.yaml строку, которая делает преобразование «import_transform: transform.create_foreign_key (« Группа »), данные загружаются, но он сохраняет это свойство как строку, нарушая мою логику приложения.

 - 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. 

2 Solutions collect form web for “Как я могу использовать bulkuploader для заполнения класса с помощью db.SelfReferenceProperty?”

Используя ответ, заданный аналогичной проблеме в качестве базы, я мог бы успешно решить эту проблему, создав небольшой файл helpers.py чтобы действовать как оболочка вокруг 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 

Как только этот файл находится в том же каталоге, что и файл конфигурации bulkloader.yaml yaml bolk ( bulkloader.yaml ), вы добавляете его в этот файл:

 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 

С этими изменениями массовая загрузка теперь работает правильно.

Прежде чем использовать это, вы должны обязательно изменить catch, except , и заменить его может быть, except BadValueError .

transform.py (возможно, только недавно) содержит декоратор, который решает эту проблему:

 def none_if_empty(fn): """A decorator which returns None if its input is empty else fn(x). Useful on import. Can be used in config files (eg "transform.none_if_empty(int)" or as a decorator. Args: fn: Single argument transform function. Returns: Wrapped function. """ def wrapper(value): if value == '' or value is None or value == []: return None return fn(value) return wrapper 

Таким образом, использование следующего будет также решить проблему без введения пользовательского файла helpers.py :

 transform.none_if_empty(transform.create_foreign_key('Group')) 
  • Может ли библиотека запросов Python использоваться в Google App Engine?
  • Синглеты Google App Engine (Python)
  • Как обслуживать файлы cloudstorage с помощью SDK приложения
  • Создайте хороший URL-адрес для ключа с предками
  • Получение «Обновление из-за 401» при попытке подключения с помощью remote_api
  • Как работают очереди задач Google App Engine?
  • Можно ли получить доступ к ключевому имени объекта изнутри шаблона jinja2?
  • Разница между Flask и Webapp2 (GAE)
  • Как установить ndb keyProperty
  • Хостинг нетривиальной программы python в Интернете?
  • i18n с jinja2 + GAE
  • Python - лучший язык программирования в мире.