Обход пирамиды __name__ соответствует имени представления

Как в приложении Traversal-пирамиды обрабатывать ресурс с __name__, который соответствует имени представления?

Если бы я хотел перейти к вызываемому представлению «представление» для ресурса, я бы использовал URL-адрес, например: /foo/bar/view. Он проходит через resource_tree следующим образом:

RootFactory(request) => RootFactory
RootFactory['foo']   => Foo
Foo['bar']           => Bar
Bar['view']          => KeyError

... и поскольку он не может пройти мимо Bar, а "представление" осталось, оно предполагает, что "представление" - это имя представления и соответствует моему вызываемому представлению.

@view_config(name='view')
def view(context, request):
    return Response(context.__name__)

Чтобы получить URL-адрес для этого пути, я бы использовал request.resource_url(resource, "view").

Однако, если бы у меня был такой ресурс, как Bar.__name__ = "view", как я могу разрешить URL-адрес для «просмотра» на Foo?

# path: /foo/view
RootFactory(request) => RootFactory
RootFactory['foo']   => Foo  # ideally stop here with view_name="view"
Foo['view']          => Bar.__name__ = "view"
# all parts of path matched so view_name="" and context=Bar

В идеале в этой ситуации /foo/view указывало бы на view(Foo, request), а /foo/view/view указывало бы на view(Bar, request), где Bar.__name__ == "view".

Есть ли способ справиться с этим без записи обнаружения коллизий между __name__ и именами представлений?


person Far_Eggs    schedule 13.05.2016    source источник


Ответы (1)


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

Ниже приведен пример структуры ресурсов:

class Foo(object):

    def __init__(self, parent, name):
        self.__parent__ = parent
        self.__name__ = name

    def __getitem__(self, key):
        if key == "bar":
            return BarContainer(self, "bar")
        else:
            raise KeyError()

class BarContainer(object):

    def __init__(self, parent, name):
        self.__parent__ = parent
        self.__name__ = name

    def __getitem__(self, key):
        return Bar(self, key)

class Bar(object):

    def __init__(self, parent, name):
        self.__parent__ = parent
        self.__name__ = name

В вопросе упоминается желание сгенерировать URL-адреса ресурсов для вызываемого озаглавленного представления. С BarContainer это просто добавляет дополнительную косую черту:

/{foo}/bar/{bar}/<view_name>    
/a/view          => view(context=Foo(name='a'), request)
/a/bar/view      => view(context=BarContainer(name='bar'), request)
/a/bar/b/view    => view(context=Bar(name='b'), request)
person Far_Eggs    schedule 16.05.2016