переменная доступа, объявленная в дочернем шаблоне или в переменных контроллера - PullRequest
4 голосов
/ 05 апреля 2011

У меня есть небольшая иерархия шаблонов мако, которые выглядят примерно так:

base.mako

<h1>${self.view()}</h1>
${listactions(self.mainactions)}
${self.body()}

<%def name="listactions(actions)">
    <ul>
    % for action in actions:
        <li>${action}</li>
    % endfor
    </ul>
</%def>

clientsbase.mako

<%inherit file="base.mako"/>
<%def name="view()">Clients</%def>
<%
    mainactions = [request.route_url('clientsnew')]
%>

clientsindex.mako

<%inherit file="clientsbase.mako"/>
This is the index

Проблема в том, что когда я пытаюсь получить доступ к индексу представления клиентов, который отображает clientsindex.mako, я получаю сообщение об ошибке AttributeError: Пространство имен 'self: /base.mako' не имеет члена 'mainactions' .

Каким должен быть правильный способ сделать это? Я просмотрел документацию по mako, и то, что я нашел до сих пор, - это то, что я могу использовать python-блок на уровне модуля для объявления связей, а затем в base.mako просто сделать self.attr.mainactions . Проблема в том, что внутри этого блока у меня нет доступа к объекту запроса.

Я предполагаю, что еще один вопрос: в моем случае я использую функции в качестве вызываемых для представления, но, допустим, я написал отдельный файл представления client.py, который содержит все представления, связанные с клиентами. Есть ли способ как-то установить переменные контекста контроллера в файле client.py? Таким образом, я мог бы уже установить переменную mainactions в контексте шаблона, не возвращая ее в каждом представлении.

Ответы [ 4 ]

1 голос
/ 28 июня 2012

Это довольно старый вопрос, но здесь, я думаю, это может сработать. Помните, что когда вы пишете шаблон, вы по умолчанию отображаете функцию body().

Я предполагаю, что mainactions определяется как локальная переменная для self.body(). Но все круто, так как у нас есть доступ к себе ...

поэтому вместо записи:

mainactions = [request.route_url('clientsnew')]

Вы должны попробовать написать:

self.mainactions = [request.route_url('clientsnew')]

Тем не менее, это не очень хороший способ достичь того, что вы хотели сделать. На вашем месте я бы сделал это, используя def или block.

base.mako

<h1>${self.view()}</h1>
<%block name="mainaction">
</%block>
${self.body()}

<%def name="listactions(actions)">
    <ul>
    % for action in actions:
        <li>${action}</li>
    % endfor
    </ul>
</%def>

clientbase.mako

<%inherit file="base.mako"/>
<%def name="view()">Clients</%def>
<%block name="mainaction"
    ${request.route_url('clientsnew')}
</%block>

Остальное не меняется ... С помощью def вы просто переопределяете def от родителя, а затем в base.mako вы используете def там, где хотите.

Вот и все.

0 голосов
/ 12 сентября 2012

Этот ответ на ваш «другой вопрос»:)

Вы можете определить свои представления как методы класса Controller.Таким образом, вы можете преобразовать вывод переменной на уровне контроллера в общий метод:

from pyramid.view import view_config
from myproject.resources import MyResource


class MyController(object):

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

    def respond(self, additionalVars):
        additionalVars['myCommonVar1'] = 'common value'
        return additionalVars

    @view_config(
        context='myproject.resources:MyResource',
        request_method='GET',
        renderer='one.mak')
    def get_one(self):
        return self.respond({'var2':'sth'})

    @view_config(
        context='myproject.resources:MyResource',
        name = 'two',
        request_method='GET',
        renderer='two.mak')
    def get_two(self):
        return self.respond({'var3':'sth else'})
0 голосов
/ 14 декабря 2011

этот ответ старый, поэтому я не знаю, решили ли вы уже эту проблему.

Один из способов, который может сработать, - это перемещение вашего блока python в пределах view () def.Таким образом, эта переменная будет фактически вызываться в base.mako.

В моем собственном приложении я создал объект view, который содержит набор контекстных переменных, которые мне нужны во всем приложении, например view.page, view.perpage и т. д. При каждом вызываемом представлении я запускаю это view (автоматически вычисляет контекстные переменные из get, post_data, маршрутов и т. д.) и передаю его как переменную контекста.Таким образом, вы всегда можете передать view.mainactions, и вы не столкнетесь с какими-либо KeyErrors в вашем приложении, если вы оставите его по умолчанию None.

0 голосов
/ 06 апреля 2011

Хммм ... Я давно ничего не писал в пилонах, и при этом у меня нет установки пилонов, чтобы проверить это.Но, пожалуйста, попробуйте написать next.mainactions вместо self.mainactions и посмотрите, что произойдет.

...