Django學習系列12:把Python變量傳入模板中渲染


從視圖的Python代碼中把變量傳入HTML模板。

模板中使用哪種句法引入Python對象,要使用的符號{{...}},它會以字符串的形式顯示對象:

<html>
    <head>
        <title>To-Do lists</title>
    </head>>
    <body>
        <h1>Your To-Do list</h1>
        <form method="POST">
            <input name="item_text" id="id_new_item" placeholder="Enter a to-do item" />
            {% csrf_token %}
        </form>

        <table id="id_list_table">
            <tr><td>{{ new_item_text}}</td></tr>
        </table>
    </body>
</html>

怎么測試視圖函數為new_item_text傳入的值正確呢?怎么把變量傳入模板呢?

可以在單元測試中實際操作一遍找出這兩個問題的答案。(前面我們用到了render_to_string函數,用它手動渲染模板,然后拿它的返回值和視圖函數返回的HTML比較)

讓我們調整單元測試,以便它檢查我們是否仍在使用模板:

lists/tests.py

    def test_can_save_a_post_request(self):
        response = self.client.post('/', data={'item_text':'A new list item'})
        self.assertIn('A new list item', response.content.decode())
        self.assertTemplateUsed(response, 'home.html')

如預期那樣失敗:

AssertionError: No templates used to render the response

很好,我們故意編寫愚蠢的返回值已經騙不過我們的測試,因此要重寫視圖函數,把post請求中的參數傳遞給模板。render函數將映射模板的字典作為其第三個參數變量名到其值:

lists/views.py

from django.shortcuts import render
from django.http import HttpResponse

# Create your views here.在這兒編寫視圖
def home_page(request):
    return render(request, 'home.html', {
        'new_item_text':request.POST['item_text'],
    })

運行單元測試

django.utils.datastructures.MultiValueDictKeyError: "'item_text'"

這次失敗發生在另一個測試中,修正的方法如下:

lists/views.py

from django.shortcuts import render
from django.http import HttpResponse

# Create your views here.在這兒編寫視圖
def home_page(request):
    return render(request, 'home.html', {
        'new_item_text': request.POST.get('item_text', ''),
    })

單元測試通過

看看功能測試結果:

AssertionError: False is not true : New to-do item did not appear in table 

錯誤信息沒有多大幫助,使用另一種功能測試的調試技術:改進錯誤信息。

#  functional_tests.py

        self.assertTrue(
            any(row.text == '1: Buy peacock feathers' for row in rows),  # 5
            "New to-do item did not appear in table -- its text was:\n%s" % (
                 table.text,
            )

改進后,測試給出了更有用的錯誤信息

AssertionError: False is not true : New to-do item did not appear in table -- its text was:
Buy peacock feather

怎么改效果更好,讓斷言不那么靈巧。把六行assertTrue換成一行assertIn:

        # self.assertTrue(
        #     any(row.text == '1: Buy peacock feathers' for row in rows),  # 5
        #     "New to-do item did not appear in table -- its text was:\n%s" % (
        #          table.text,
        #     )
        # )
self.assertIn('1: Buy peacock feathers', [row.text for row in rows])

修改后得到以下錯誤信息:(錯誤的意思是功能測試在枚舉列表中的項目時希望第一個項目以“1:開頭”。)

    self.assertIn("1:Buy peacock feathers", [row.text for row in rows])
AssertionError: '1:Buy peacock feathers' not found in ['Buy peacock feather']

 讓測試通過最快的方法是修改模板

            <tr><td>1:{{ new_item_text}}</td></tr>

現在功能測試能執行到self.fail。

如果擴充功能測試,檢查表格中添加的第二個待辦事項(復制粘貼),我們會發現剛才使用的簡單處理方法不奏效了。

        # 頁面再次更新,清單中顯示了這兩個待辦事項
        inputbox.send_keys(Keys.ENTER)
        time.sleep(1)

        table = self.browser.find_element_by_id('id_list_table')
        rows = table.find_elements_by_tag_name('tr')
        self.assertIn('1: Buy peacock feathers', [row.text for row in rows])
        self.assertIn('2: Use peacock feathers to make a fly', [row.text for row in rows])


        self.fail("完成測試")
        # self.assertIn('Django', self.browser.title)

這個功能測試會返回一個錯誤

AssertionError: '2: Use peacock feathers to make a fly' not found in ['1: Buy peacock feathers']

代碼提交:

$ git diff
# should show changes to functional_tests.py, home.html, tests.py and views.py
$ git commit -am “添加兩個待辦事項清單”

然后重構功能測試。使用輔助方法(放在tearDown和第一個測試之間),記住名字以test_開頭的方法才會作為測試運行,可以根據需求使用其他方法,下面在功能測試中使用輔助方法

from selenium import webdriver
from selenium.webdriver.common.keys import Keys  # 4
import time
import unittest

class NewVisitorTest(unittest.TestCase):
    def setUp(self):  # 1
        self.browser = webdriver.Firefox()
        self.browser.implicitly_wait(3)

    def tearDown(self):  # 1
        self.browser.quit()

    def check_for_row_in_list_table(self, row_text): table = self.browser.find_element_by_id('id_list_table') rows = table.find_elements_by_tag_name('tr') self.assertIn(row_text, [row.text for row in rows]) # 伊迪絲聽說了一個很酷的在線待辦事項應用程序。她去看看它的主頁
# Edith has heard about a cool new online to-do app. She goes to check out its homepage
    def test_start_a_list_and_retrieve_it_later(self):
        self.browser.get('http://localhost:8000')

        # 她注意到網頁的標題和頭部都包含“Django”.She notices the page title and header mention to-do lists
        self.assertIn('To-Do', self.browser.title)
        header_text = self.browser.find_element_by_tag_name('h1').text   # 2
        self.assertIn('To-Do', header_text)

        # 應用邀請她輸入一個待辦事項 She is invited to enter a to-do item straight away
        inputbox = self.browser.find_element_by_id('id_new_item')
        self.assertEqual(
            inputbox.get_attribute('placeholder'),
            'Enter a to-do item'
        )

        # 她在一個文本框中輸入了“buy peacock feathers(購買孔雀羽毛)”,她的愛好時用假蠅做魚餌釣魚
        inputbox.send_keys('Buy peacock feathers')

        # 頁面再次更新,清單中顯示了這兩個待辦事項
        inputbox.send_keys(Keys.ENTER)
        time.sleep(1)
        self.check_for_row_in_list_table('1: Buy peacock feathers')

        # 頁面中又顯示了一個文本框,可以輸入其他的待辦事項
        inputbox = self.browser.find_element_by_id('id_new_item')
        inputbox.send_keys('Use peacock feathers to make a fly')
        inputbox.send_keys(Keys.ENTER)
        time.sleep(1)

        # 頁面再次更新,她的清單中顯示了這兩個待辦事項
        self.check_for_row_in_list_table('1: Buy peacock feathers')
        self.check_for_row_in_list_table('2: Use peacock feathers to make a fly')

        self.fail("完成測試")
        # self.assertIn('Django', self.browser.title)

再次運行功能測試,看重構前后的表現是否一致:

AssertionError: '1: Buy peacock feathers' not found in ['1: Use peacock feathers to make a fly']

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM