2016-11-21 46 views
0

我想實現一個簡單的日曆網頁。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)])) 

因此t他的代碼只是部分工作,因爲我不知道如何使用Jinja2來渲染每個月。

任何幫助,將不勝感激。 本

+0

這很不清楚你問什麼。 「每個月」都在一個單獨的頁面中?如果是這樣,請使用'{%include'path/to/file.html'%}'這應該可以做到。如果沒有,請進一步澄清。 –

+0

我仍然不明白你到底需要什麼,試着更具體一些嗎?如果你不知道如何使頁面顯示出來。你可以在'Flask'中使用'return render_template('path/to/page.html')''。否則我不知道你在問什麼。 –

+0

感謝您的回答。最終,幾個月將在同一頁面上顯示爲列。我的問題是:基本上,呈現HTML的循環應該在模板中,以避免在Python腳本中編寫HTML。但是,在這裏我使用自定義日曆類中的方法進行迭代。那麼做到這一點的正確方法是什麼? – blaurent

回答

0

我終於認爲我得到你想要的。 不要Python中寫HTML。相反,你可以創建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)變量並將它們發送到Jinja模板通過添加第二個argumentrender_template。希望我明白這次你想要的東西。

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)) 

讓我知道,如果你看到一個更好的辦法。

謝謝。

+0

你不需要任何'html'函數。任何'HTML'腳本都應該在'.html'文件中。爲什麼你用'jinja2.FileSystemLoader'和'jinja2.Environment'?你可以在一個單獨的文件中創建這個類,將這個類包含到視圖中,創建一個類的對象,並且像在我的例子中那樣用'render_template'傳遞這個對象。然後使用'jinja'中的對象來顯示它的某些屬性。這就是我會怎麼做 –

+0

嗯,我在網絡開發新手。難道你只是提出了使用低級Jinja2和Flask框架之間的區別嗎? – blaurent

+0

說實話,我從來沒有使用過'jinja.FileSystemLoader'或者其他類似的函數。我有一個運行在Flask「http://m41kdev3lops.pythonanywhere.com/」上的網站,它功能完善,但從未使用過類似的東西。道歉,不能幫助你在那裏。 –