zoukankan      html  css  js  c++  java
  • 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:
    %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:
    %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']
  • 相关阅读:
    003 01 Android 零基础入门 01 Java基础语法 01 Java初识 03 Java程序的执行流程
    002 01 Android 零基础入门 01 Java基础语法 01 Java初识 02 Java简介
    001 01 Android 零基础入门 01 Java基础语法 01 Java初识 01 导学
    001 Android Studio 首次编译执行项目过程中遇到的几个常见问题
    Dora.Interception,为.NET Core度身打造的AOP框架 [2]:以约定的方式定义拦截器
    Dora.Interception,为.NET Core度身打造的AOP框架 [1]:更加简练的编程体验
    监视EntityFramework中的sql流转你需要知道的三种方式Log,SqlServerProfile, EFProfile
    轻量级ORM框架——第二篇:Dapper中的一些复杂操作和inner join应该注意的坑
    轻量级ORM框架——第一篇:Dapper快速学习
    CF888G Xor-MST(异或生成树模板)
  • 原文地址:https://www.cnblogs.com/ranxf/p/11676687.html
Copyright © 2011-2022 走看看