iT邦幫忙

2022 iThome 鐵人賽

DAY 21
0
Modern Web

Django 初心者之旅系列 第 21

【Day 21】Django Template Tags 補充篇(2) – For Loop

  • 分享至 

  • xImage
  •  

接下來的幾天都會是對Template Tags的補充內容,有些東西可能前面有使用過,這邊可以當作再一次的複習。為避免看起來內容水分有點重,比較簡單的內容都會被塞到同一篇,沒直接跳過這些看起來簡單的內容是為了呼應系列文的初心兩個字,我希望能將Django的入門起點拉得越低越好。

測試環境

開始測試補充篇的各種原始碼之前,我們要先建好一個用來顯示執行結果的測試網頁。
如果已經在昨天的if篇建立過測試環境,那只要更改跟昨天不一樣的地方就好了。

(忘記怎麼啟動python虛擬環境或網頁伺服器可以看前面幾篇都有提到)

  1. members/templates資料夾下新增一個檔案testing.html,之後會把各種原始碼貼進去看結果。

  1. members/views.py新增view方法,用來處理訪問tetsing.html的請求。因為要測試For Loop原始碼會需要用到Members資料表的資料,所以我們把它拿出來傳到前端網頁。

    ##上面都沒變所以省略...
    #下面是新增的內容
    def testing(request):
      Members.objects.all().values()
      mymember = template = loader.get_template('testing.html')
      context = {
        'mymember': mymember,
        'emptyObject': [], #後面測試For迴圈會用到就順便傳到前端網頁
      }
      return HttpResponse(template.render(context,request)) 
    
  2. members/urls.py註冊到testing.html的路徑,指定用剛建立的view方法來處理對該路徑的請求。

    from django.urls import path
    from . import views
    
    urlpatterns = [
      path('', views.index, name='index'),
      path('add/', views.add, name='add'),
      path('add/addrecord/', views.addrecord, name='addrecord'),
      path('delete/<int:id>', views.delete, name='delete'),
      path('update/<int:id>', views.update, name='update'),
      path('update/updaterecord/<int:id>', views.updaterecord, name='updaterecord'),
      path('testing/', views.testing , name='testing') #新增這一行
    ]
    
  3. 啟動Server等待查看每一次貼上原始碼的結果。

  4. 把各種原始碼貼進testing.html,就能在刷新頁面後,看到相應的結果囉。下面是回傳到前端網頁的Members資料表資料(QuerySet)。

    <p>{{ mymembers }}</p>
    

下面的部分例子改用{% with %}建立變數來測試執行結果,別忘記加上{% endwith %},W3Schools上面的沒有加,實際執行會有錯誤。

For Loop

如果想要重複做一件事,像是從1加到100,或者把list裡面的東西逐個拿出來,都可以透過For Loop,也就是For迴圈幫我們做到。

我們目前的Members資料表裡面的資料如下 :

<QuerySet [{'id': 1, 'firstname': 'Emil', 'lastname': 'Refsnes'},
           {'id': 2, 'firstname': 'Tobias', 'lastname': 'Refsnes'},
           {'id': 3, 'firstname': 'Linus', 'lastname': 'Refsnes'},
           {'id': 4, 'firstname': 'Lene', 'lastname': 'Refsnes'},
           {'id': 5, 'firstname': 'Stale', 'lastname': 'Refsnes'}]>

Normal For Loop

先用最原始的For迴圈把資料表的紀錄(Record)從頭到尾逐個拿出來放到表格裡面吧!

下面把從Members資料表傳到前端的資料(mymemberscontext裡面的key)順向逐個拿出來放到x,此時每個x都是object,接下來用OOP的方式取出物件屬性值。

<table border="1">
  {% for x in mymembers %}
  <tr>
    <td>{{ x.id }}</td>
    <td>{{ x.firstname }}</td>
    <td>{{ x.lastname }}</td>
  </tr>
  {% endfor %}
</table> 

Reversed For Loop

Normal For Loop不一樣的地方在於把資料表的紀錄(Record)從尾到頭的拿出來放到表格裡面。

下面把從Members資料表傳到前端的資料(mymemberscontext裡面的key)逆向逐個拿出來放到x,此時每個x都是object,接下來用OOP的方式取出物件屬性值。

<table border="1">
  {% for x in mymembers reversed %}
  <tr>
    <td>{{ x.id }}</td>
    <td>{{ x.firstname }}</td>
    <td>{{ x.lastname }}</td>
  </tr>
  {% endfor %}
</table> 

Empty Object In For Loop

如果在做For迴圈的時候遇到空物件(Empty Object)該怎麼辦? 如果不做處理肯定會出錯,所以我們可以在For迴圈裡面加上特殊的Django Template Tag : {% empty %}

For迴圈裡面加上{% empty %}以後,若執行迴圈遇到空物件,就會去執行{% empty %}後面的區塊,像下面遇到空物件就會顯示None

<table border="1">
  {% for x in emptyObject %}
  <tr>
    <td>{{ x.id }}</td>
    <td>{{ x.firstname }}</td>
    <td>{{ x.lastname }}</td>
    {% empty %}
    <td>None</td>
    <td>None</td>
    <td>None</td>
  </tr>
  {% endfor %}
</table> 

For Loop Variable

Django的For迴圈裡面有一些特殊的變數可以使用,像是下面列的這些。

  • forloop.counter

    • 設置從1開始的計數器(counter),總共會累加Object個數-1次。
    {% with Numbers1='123456'%}
    {% for x in Numbers1 %}
      <p>Loop counter: {{forloop.counter}}</p>
    {% endfor %}
    {% endwith %}
    

  • forloop.counter0

    • 設置從0開始的計數器(counter),總共會累加Object個數-1次。
    {% with Numbers1='123456'%}
    {% for x in Numbers1 %}
      <p>Loop counter: {{forloop.counter0}}</p>
    {% endfor %}
    {% endwith %}
    

  • forloop.first

    • 可以用來判斷是否是初次執行迴圈(counter = 1)。
    {% with Numbers1='123456'%}
    {% for x in Numbers1 %}
      {% if forloop.first %}
        <p>First Loop</p>
      {% else %}
        <p>Not First Loop</p>
      {% endif %}
    {% endfor %}
    {% endwith %}
    

  • forloop.last

    • 可以用來判斷是否是最後一次執行迴圈(counter = object個數)。
    {% with Numbers1='123456'%}
    {% for x in Numbers1 %}
      {% if forloop.last %}
        <p>Last Loop</p>
      {% else %}
        <p>Not Last Loop</p>
      {% endif %}
    {% endfor %}
    {% endwith %}
    

  • forloop.parentloop

    • 有2層以上的For迴圈的話,內迴圈可以用它來取得外迴圈的For Loop Variable
    {% with Numbers1='12' Numbers2='123' %}
    {% for x in Numbers1 %}
      {% for y in Numbers2 %}
      <p>Parent loop counter: {{forloop.parentloop.counter}}<br>
      Loop counter: {{forloop.counter}}</p>
      {% endfor %}
    {% endfor %}
    {% endwith %}
    

    可以看到內、外迴圈計數器的不同。

  • forloop.revcounter

    • 設置從object個數開始的計數器(counter),總共會累減Object個數-1次,最後回到1。
    {% with Numbers1='123456'%}
    {% for x in Numbers1 %}
      <p>Loop counter: {{forloop.revcounter}}</p>
    {% endfor %}
    {% endwith %}
    

  • forloop.revcounter0

    • 設置從object個數-1開始的計數器(counter),總共會累減Object個數-1次,最後回到0。
    {% with Numbers1='123456'%}
    {% for x in Numbers1 %}
      <p>Loop counter: {{forloop.revcounter0}}</p>
    {% endfor %}
    {% endwith %}
    

明天會是Django Template Tags 補充的第3篇 - Cycle & Comment。


上一篇
【Day 20】Django Template Tags 補充篇(1) – If & Logical Operators
下一篇
【Day 22】Django Template Tags 補充篇(3) – Cycle & Comment
系列文
Django 初心者之旅31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
hokou
iT邦好手 1 級 ‧ 2022-10-06 09:16:52

有個小疑問,Template Tags 有管 Python 的縮排嗎?
主要是 {% empty %} 這段怎麼會知道包含底下 3 個 <td> 而沒有 </tr>

<table border="1">
  {% for x in emptyObject %}
  <tr>
    <td>{{ x.id }}</td>
    <td>{{ x.firstname }}</td>
    <td>{{ x.lastname }}</td>
    {% empty %}
    <td>None</td>
    <td>None</td>
    <td>None</td>
  </tr>
  {% endfor %}
</table> 

謝謝

Xiang1009 iT邦研究生 4 級 ‧ 2022-10-07 01:53:04 檢舉
<table border="1">
  {% for x in emptyObject %}
  <tr>
    <td>{{ x.id }}</td>
    <td>{{ x.firstname }}</td>
    <td>{{ x.lastname }}</td>
{%empty%}
<td>None</td>
  <td>None</td>
<td>None</td>
  </tr>
  {% endfor %}
</table> 

上面稍微打亂縮排,結果還是一樣。

Template Tags 沒有管 Python 的縮排,它比較像是用階層來區分,{% empty %}上面的<td>和下面的<td>屬於同一層的sibiling,而外層的<tr>則是它們的parent。

我要留言

立即登入留言