DocTest не работает при создании объекта

У меня проблема с doctest, потому что я пытаюсь переименовать идентификаторы объекта типа контента в обработчике IObjectAddedEvent. Мое требование состоит в том, чтобы иметь идентификаторы, которые являются последовательными и зависят от контекста, например, CAM-001, CAM-002, BLK-001, BLK-002 и т. д.

Когда я добавляю объект вручную в браузере, обработчик событий правильно переименовывает идентификатор, но когда я пытаюсь создать его в doctest, он терпит неудачу вскоре после его добавления в контейнер. plone.dexterity addContentToContainer вызывает _setObject с исходным идентификатором, затем обработчик событий срабатывает и переименовывает идентификатор, а затем, когда _getObject использует исходный идентификатор, он, очевидно, не может найти объект, поэтому он бомбит с ошибкой атрибута.

Я создал продукт, чтобы проиллюстрировать это здесь https://github.com/mikejmets/wt.testrig. .

Я также пытался использовать plone.api в doctest, но это тоже не помогло.

Приветствуются все идеи.


person Mike    schedule 27.11.2014    source источник
comment
что-нибудь не так с моим ответом?   -  person Mathias    schedule 01.12.2014


Ответы (1)


Поскольку вы используете ловкость, лучшим решением будет написать собственное NameGenerator поведение.

Я предполагаю, что ваш DX-контент активировал следующее поведение: <element value="plone.app.content.interfaces.INameFromTitle" />

Это поведение отвечает за переименование элемента после создания. Вы должны удалить это и добавить свое собственное.

Пример:

Зарегистрируйте поведение с помощью zcml.

<plone:behavior
    title="Special name(id) generator"
    description=""
    provides="dotted.name.to.your.INameGenerator"
    factory="dotted.name.to.your.name_generator.NameGenerator"
    for="dotted.name.to.content.interface"
    />

Соответствующий код Python.

from plone.app.content.interfaces import INameFromTitle
from zope.component import getUtility
from zope.interface import implements


class INameGenerator(INameFromTitle):
    """Behavior interface.
    """


class NameGenerator(object):
    """Customized name from title behavior."
    """

    implements(INameGenerator)


    def __init__(self, context):
        self.context = context

    @property
    def title(self):

        # YOUR IMPLEMENTATION
        title = ...

        return title

ВАЖНО: Наследуйте свой интерфейс от INameFromTitle

Теперь добавьте <element value="dotted.name.to.your.INameGenerator" /> к поведению содержимого.

Вероятно, удаления поведения INameFromTitle из вашего типа контента может быть достаточно, но лучше было бы явно реализовать собственное поведение.

person Mathias    schedule 28.11.2014
comment
Спасибо @Mathias, ваше решение намного чище. К сожалению, в этом случае я использую контейнер для определения нового идентификатора, а объект еще не добавлен в контейнер. Я собираюсь создать форму AddForm, которая генерирует новый идентификатор и передает его при создании объекта. - person Mike; 02.12.2014
comment
Вы можете получить доступ к контейнеру с помощью self.context.aq_parent, или есть проблема сделать это позже? Удаление поведения INameFromTitle из вашего контента тоже не помогло? - person Mathias; 02.12.2014
comment
На данный момент новый объект не имеет родителя, я предполагаю, что он еще не был добавлен в свой контейнер. И я уже удалил поведение INameFromTitle. Мой текущий обходной путь — это пользовательская форма AddForm, которая передает идентификатор методу создания, но я думаю, что мне следует смотреть на сервер идентификаторов, а не создавать его на основе идентификаторов одноранговых объектов. - person Mike; 05.12.2014