【问题标题】:How to properly call functions in templates?如何正确调用模板中的函数?
【发布时间】:2017-08-11 02:39:08
【问题描述】:

好的,我学到了一点,现在可以在 web.py 中复制我的网站,但我不喜欢我在某些地方的做法。

1) 我希望能够在不调用 Main 的情况下调用模板。

2) 我希望能够从布局中调用函数。

对以上内容的任何建议都会有所帮助,在此先感谢您。

以下是代码的简化版本,可让您了解正在发生的事情。如果我错过了发布重要内容,请告诉我。

code.py:

import web
import Universal
import Navigation
import Content
import Versions


urls = (
    '/favicon.ico', 'icon',
    '/', 'index',
    '/Section1/index', 'Section1',
    '/Section2/index', 'Section2',
    '/Section3/index', 'Section3'
)

app = web.application(urls, globals(), autoreload=True)
render = web.template.render('templates/')#, base='Layout')

static = web.template.render('static/')

Main = web.template.render('templates/')
Section1 = web.template.render('templates/Section1/')
Section2 = web.template.render('templates/Section2/')
Section3 = web.template.render('templates/Section3/')

class static:
    def GET(self):
        return static()

#class icon:
#    def GET(self):
#        return static.favicon()

class index:
    def GET(self):
        vPage = '0'
        vLevel = '0'
        vSection = '0'
        vHead = Universal.getHead(vSection)
        vHeader = Universal.getHeader()
        vNavBar = Universal.getNavBar()
        vNavigation = Navigation.getNavigation(vLevel)
        vContent = Content.getContent(vLevel)
        vVersions = Versions.getVersions(vLevel)
        vFooter = Universal.getFooter()
        return Main.Layout(vHead, vHeader, vNavBar, vNavigation, vContent, vVersions, vFooter)

class Section1:
    def GET(self):
        vPage = '0'
        vLevel = '1'
        vSection = '1'
        vHead = Universal.getHead(vSection)
        vHeader = Universal.getHeader()
        vNavBar = Universal.getNavBar()
        vNavigation = Navigation.getNavigation(vLevel)
        vContent = Content.getContent(vLevel)
        vVersions = Versions.getVersions(vLevel)
        vFooter = Universal.getFooter()
        return Main.Section1.Layout(vHead, vHeader, vNavBar, vNavigation, vContent, vVersions, vFooter)

class Section2:
    def GET(self):
        vPage = '0'
        vLevel = '2'
        vSection = '2'
        vHead = Universal.getHead(vSection)
        vHeader = Universal.getHeader()
        vNavBar = Universal.getNavBar()
        vNavigation = Navigation.getNavigation(vLevel)
        vContent = Content.getContent(vLevel)
        vVersions = Versions.getVersions(vLevel)
        vFooter = Universal.getFooter()
        return Main.Section2.Layout(vHead, vHeader, vNavBar, vNavigation, vContent, vVersions, vFooter)

class Section3:
    def GET(self):
        vPage = '0'
        vLevel = '3'
        vSection = '3'
        vHead = Universal.getHead(vSection)
        vHeader = Universal.getHeader()
        vNavBar = Universal.getNavBar()
        vNavigation = Navigation.getNavigation(vLevel)
        vContent = Content.getContent(vLevel)
        vVersions = Versions.getVersions(vLevel)
        vFooter = Universal.getFooter()
        #return render.Layout(vHead, vHeader, vNavBar, vNavigation, vContent, vVersions, vFooter)
        return Main.Section3.Layout(vHead, vHeader, vNavBar, vNavigation, vContent, vVersions, vFooter)

模板/Layout.html:

$def with (vHead, vHeader, vNavBar, vNavigation, vContent, vVersions, vFooter)

<html>
<head>
    $:vHead
</head>
<body id="idBody">
    <table id="idTableMain">
        <tr id="idHeaderRow">
            <td id="idHeaderRowCenter" colspan="3">
                $:vHeader
            </td>
        </tr>
        <tr id="idNavigationRow">
            <td id="idNavigationBar" colspan="3">
                $:vNavBar
            </td>
        </tr>               
        <tr id="idCenterRow">
            <td id="idCenterRowLeft">
                <h4>
                    Navigation
                </h4>
                $:vNavigation
            </td>
            <td id="idCenterRowMain">
                $:vContent
            </td>
            <td id="idCenterRowRight">
                <h4>
                    Information
                </h4>
                This was written with Python 2.7 and web.py.<br><br>
                Other versions of this page are here:<br>
                $:vVersions
            </td>   
        </tr>
        <tr id="idFooterRow">
            <td id="idFooterMain" colspan="3">
                $:vFooter
            </td>
        </tr>
    </table>
</body>
</html>

Universal.py

def getHead(vSection):
    vResult = '<meta http-equiv=\"Content-Type\" content=\"text/html; charset=ISO-8859-1\">'
    vResult += '<link href=' + getCSS(vSection) + ' rel=\"stylesheet\" type="text/css">'
    return vResult

def getCSS(vSection):
    if vSection == '1':
        vResult = '/static/Section1/Section1.css'
    elif vSection == '2':
        vResult = '/static/Section2/Section2.css'
    elif vSection == '3':
        vResult = '/static/Section3/Section3.css'
    else:
        vResult = '/static/Main.css'
    return vResult

def getHeader():
    vResult = '<img id=\"idLogo\" src=' + getLogo() + '>'
    return vResult
def getNavBar():
    vResult = '<a class=\'navBar\' href=\'/index\'>Home</a>'
    vResult += '<a class=\'navBar\' href=\'/Section1/index\'>Web Programming</a>'
    vResult += '<a class=\'navBar\' href=\'/Section2/index\'>Private Projects</a>'
    vResult += '<a class=\'navBar\' href=\'/Section3/index\'>Downloadable Projects</a>'
    return vResult

【问题讨论】:

    标签: python function templates web.py


    【解决方案1】:

    web.py 模板使用白名单来识别可以在模板中执行的功能。您可以通过创建一个字典并将其传递给您的渲染器来添加它。例如:

    common_globals = {'getHeader': Universal.getHeader,
                      'getCSS': Universal.getCSS,
                      'getHead': Universal.getHead,
                      'getNavBar': Universal.getNavBar}
    Main = web.template.render('templates/')
    Section1 = web.template.render('templates/Section1/', globals=common_globals)
    Section2 = web.template.render('templates/Section2/', globals=common_globals)
    Section3 = web.template.render('templates/Section3/', globals=common_globals)
    

    然后,在你Layout.html 内你可以这样做:

    $def with(page, level, section)
    <html>
    <head>
        $:getHead(section)
    </head>
    etc....
    

    ...然后您在 code.py 中对 Section2 类的调用如下所示:

    class Section2(object):
        def GET(self):
            return Main.Section2.Layout(page=0, level=2, section=2)
    

    (实际上,我认为您不需要调用 Main,只需渲染为 return Section2.Layout(0, 2, 2)

    对其他部分重复并更新您的布局以直接调用您的函数,它将起作用。

    【讨论】:

    • 谢谢@pbuck!我一直在为 dict 寻找一些东西,但无法将它拼凑成我需要的东西。期待在我可以尝试的时候尝试。
    • 对于 Main 与 Section2 的问题,你的建议是我打算如何做的,但我不断收到类似“这里没有项目名称布局”的信息,不得不做 Main.Section2。 ...等以获取不同的模板。我会在你的第一个建议后重新尝试。 :)
    • 我不确定你想用MainSection1 等做什么。如果它们只是不同的页面,那么也许你应该使用单个渲染器(@987654329 @),并让该渲染器调用模板页面 (Layout),每次提供不同的参数值。如果它们代表不同的页面样式(例如“主页”、“帮助页面”等),那么您可以将相同的渲染器(“Main”)与不同的模板页面(“home.html”、“help.html”等.) 为每个特定页面实例提供不同的参数值(即 Main.help(title="Login Help", description=...), Main.help('Privacy', '...')
    • 这个项目的部分目的是模仿现有的网页,所以我试图找到尽可能多地保留文件结构的方法。在当前模型下,每个目录级别都有一个布局(或模板),因此最初的计划是调用 Section2_4 的渲染器,如下所示: Section2_4 = web.template.render('templates/Section2/Section4/')反对 return Main.Section2.Section4.Layout(vHead, vHeader, vNavBar, vNavigation, vContent, vVersions, vFooter) 但它可能是在模板文件夹中执行独特布局(如 Layout2_4)的 python 方式。
    • 使用不同的模板,每个目录一个,也可以工作——如果每个目录需要不同的格式,这可能是有意义的。如果除了标题/标题/数据之外每个目录都是“相同的”,那么使用单个模板会使事情变得更容易恕我直言。
    【解决方案2】:

    这一点真的归功于@pbuck。问题的第一部分通过使用 dict 并更新所有内容以匹配它来解决:

    code.py 中的字典:

    common_globals = {'getHead': Universal.getHead,
                        'getCSS': Universal.getCSS,
                        'getHeader': Universal.getHeader,
                        'getLogo': Universal.getLogo,
                        'getNavBar': Universal.getNavBar,
                        'getFooter': Universal.getFooter,
                        'getNavigation': Navigation.getNavigation,
                        'getContent': Content.getContent,
                        'getVersions': Versions.getVersions
                        }
    

    code.py 中的页面引用

    class index:
        def GET(self):
            vPage = '0'
            vLevel = '0'
            vSection = '0'
            return Main.Layout(vPage, vLevel, vSection)
    

    模板/Layout.html $def with (vPage, vLevel, vSection)

    <html>
    <head>
        $:getHead(vSection)
    </head>
    <body id="idBody">
        <table id="idTableMain">
            <tr id="idHeaderRow">
                <td id="idHeaderRowCenter" colspan="3">
                    $:getHeader()
                </td>
            </tr>
            <tr id="idNavigationRow">
                <td id="idNavigationBar" colspan="3">
                    $:getNavBar()
                </td>
            </tr>               
            <tr id="idCenterRow">
                <td id="idCenterRowLeft">
                    <h4>
                        Navigation
                    </h4>
                    $:getNavigation(vLevel)
                </td>
                <td id="idCenterRowMain">
                    $:getContent(vLevel+'_'+vPage+'P')
                </td>
                <td id="idCenterRowRight">
                    <h4>
                        Information
                    </h4>
                    This was written with Python 2.7 and web.py.<br><br>
                    Other versions of this page are here:<br>
                    $:getVersions(vLevel+'_'+vPage+'P')
                </td>   
            </tr>
            <tr id="idFooterRow">
                <td id="idFooterMain" colspan="3">
                    $:getFooter()
                </td>
            </tr>
        </table>
    </body>
    </html>
    

    我知道这并不花哨,但这是一个很棒的学习练习。唯一剩下的是渲染器问题,而这更多的是关于 Code.py 中的工作发生在哪里

    我可能会将其作为一个单独的问题发布。

    【讨论】:

    • 很高兴它对你有用!随意“接受”我的回答。
    猜你喜欢
    • 1970-01-01
    • 2020-04-15
    • 1970-01-01
    • 2017-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-11
    • 2019-12-10
    相关资源
    最近更新 更多