Jinja2:编写[不那么]复杂模板

时间:2016-11-21 14:44:12

标签: python django flask jinja2

我正在尝试实现一个简单的日历网页。

我对Jinja2很新,但我对模板的理解是应该避免在Python源代码中编写HTML代码,因为模板是为此目的而设计的。

我面临的问题是我没有看到如何为这个项目编写清晰的模板。我想我的项目中存在整体架构问题......

我的页面模板:

{% extends "base.html" %}
{% block title %}The title{% endblock %}
{% block content %}
    <h1>Hey</h1>
    <p> I'm happy </p>
    <div id="calendar">
        <table>
            <tr>
                {% for month in range(1, 13) %}
                    <td valign="top" align="center">{# html code for a single month goes here... #}</td>
                {% endfor %}
            </tr>
        </table>
    </div>
{% endblock %}

每月模板

<table>
    <th>{{ month_name }}</th>
    {% for day_number in days %}
        <tr><td>{{ day_number }}</td><td>{{ weekday }}</td></tr>
    {% endfor %}
</table>

最后,我有一个日历的Python类,基本上提供帮助函数来计算一个月的日期:

class Calendar:
    def __init__(self, year):
        self.year = year

    def monthrange(self, month):
        nextmonth = month % 12 + 1
        nextyear = self.year + 1 if nextmonth == 1 else self.year
        firstday = datetime.date(self.year, month, 1)
        lastday = datetime.date(nextyear, nextmonth, 1)
        return (1, (lastday - firstday).days)

    def itermonthdates(self, month):
        first, last = self.monthrange(month)
        for i in range(first, last + 1):
            yield datetime.date(self.year, month, i)

    def tohtml(self):
        def month_to_html(month):
            # !!! This code generate HTML but it should not !!!
            s = '<table>\n'
            s += '<th>{}</th>'.format(MONTHS[month - 1])
            for day in self.itermonthdates(month):
                weekday = WEEKDAYS[day.weekday()]
                d = {'day': day.day, 'weekday': weekday}
                s += '<tr><td>%(day)02d</td><td>%(weekday)s</td></tr>\n' % d
            s += '</table>\n'
            return s

        template_loader = jinja2.FileSystemLoader(searchpath='templates')
        template_env = jinja2.Environment(loader=template_loader)
        template = template_env.get_template('template.html')
        print(template.render(months=[month_to_html(i) for i in range(1, 13)]))

所以这段代码只能部分工作,因为我不知道每个月如何使用Jinja2渲染。

任何帮助将不胜感激。 本

2 个答案:

答案 0 :(得分:0)

我终于我得到了你想要的东西。 不要HTML中写Python。相反,您可以在logic中为日历创建Python,然后将该数据发送到要填充Jinja的模板。足够的谈话,让我们编写一个非常简单的例子。

简单示例

这里我们将获取当前日期以显示在网页中。

logic.py

@app.route('/')
def index():
    import time
    current_time = time.strftime("%d/%m/%Y")
    return render_template('template.html', data = current_time)

template.html

{% if data %} # This checks if the variable "data" is set.
     <p> {{data}} </p> ## This will output the date here

通过将其应用于您的代码,您可以向变量发送任何逻辑数据(这意味着需要生成Python),并通过添加第二个{{1}将其发送到Jinja模板到argument。希望我这次理解你想要的东西。

答案 1 :(得分:0)

感谢您的回答。 我以解决方案结束了。不知道是否有更好的方法。最后,我将calendar对象传递给模板。

页面模板:

{% extends "base.html" %}
{% block title %}The title{% endblock %}
{% block content %}
    <h1>Hey</h1>
    <p> I'm happy </p>
    <div id="calendar">
        <table>
            <tr>
                {% for month in range(1, 13) %}
                <td valign="top" align="center">
                    {% include 'month_template.html' %}
                </td>
                {% endfor %}
            </tr>
        </table>
    </div>
{% endblock %}

月份模板:

<table>
    <th>{{ calendar.month_name(month) }}</th>
    {% for day_number, weekday in calendar.itermonthdays(month) %}
        <tr><td>{{ day_number }}</td><td>{{ weekday }}</td></tr>
    {% endfor %}
</table>

Python脚本:

class Calendar:
    def __init__(self, year):
        self.year = year

    @staticmethod
    def month_name(monthid):
        return MONTHS[monthid - 1]

    def monthrange(self, month):
        nextmonth = month % 12 + 1
        nextyear = self.year + 1 if nextmonth == 1 else self.year
        firstday = datetime.date(self.year, month, 1)
        lastday = datetime.date(nextyear, nextmonth, 1)
        return (1, (lastday - firstday).days)

    def itermonthdates(self, month):
        first, last = self.monthrange(month)
        for i in range(first, last + 1):
            yield datetime.date(self.year, month, i)

    def itermonthdays(self, month):
        for date in self.itermonthdates(month):
            day = '{:02d}'.format(date.day)
            weekday = WEEKDAYS[date.weekday()]
            yield day, weekday

    def tohtml(self):
        template_loader = jinja2.FileSystemLoader(searchpath='templates')
        template_env = jinja2.Environment(loader=template_loader)
        template = template_env.get_template('template.html')
        print(template.render(calendar=self))

如果您看到更好的方法,请告诉我。

感谢。