Как я могу использовать 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')) 
  • Как работают очереди задач Google App Engine?
  • Сортировка WTForms form.errors dict
  • Загрузите файл приложения Google AppEngine Python и прочитайте его.
  • Присутствие API канала не запускается
  • Конечные точки OAuth от Google App Engine, бросающие 400 в производство
  • Можно ли добавлять заголовки в электронные письма, отправляемые приложением?
  • Google App Engine добавляет изображение на страницу со статической папкой
  • Как проверить, является ли дата-время старше 20 секунд
  •  
    Interesting Posts for Van-Lav
    Python - лучший язык программирования в мире.