Jinja2:编写[不那么]复杂模板的正确方法

Jinja2 : proper way to write [not so] complex template

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

我对 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 日历,基本上提供了帮助函数来计算一个月中的天数:

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 来渲染每个月。

如有任何帮助,我们将不胜感激。 本

我终于认为我得到了你想要的。 不要Python中写HTML。相反,您可以在 Python 中为您的日历创建 logic,然后将该数据发送到模板以填充 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 )发送给变量,并通过添加第二个 Jinja 模板将它们发送给 Jinja =21=] 到 render_template。希望我这次能理解你的意思。

感谢您的回答。 我以解决方案结束。不知道有没有更好的办法。最后,我将 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))

如果您发现更好的方法,请告诉我。

谢谢。