5.1 编写表单发送Post请求

5.1 在上个章节做功能测试时测试指出无法保存用户输入。
解决这个问题 的办法就是:编写表单,发送Post 请求 如何做
1、给Input 添加属性name =
2\放入 标签 添加 属性 post

<html>
    <head>
        <title>To-Do list</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"/>
        </form>
        <table id="id_list_table">
        </table>
    </body>
</html>

运行测试爆出错误 功能测试functhion_test.py
在这里插入图片描述提示无法定位到 这个元素id = " id_list_table"
似乎还没到这就结束了
看一下浏览器爆出的错误,修改一下我们的休眠时间让他不要那么快关闭页面
看到下面的内容:
在这里插入图片描述
可以看出 Csrf 这个词高频次的出现
提示我们CSRF验证失败了,原来是跨站请求伪造漏洞的问题,
如何解决这个问题呢,Django 已经提供了解决办法
在解决之前我们先来回顾一下什么是CSRF ,用一个小故事说明
王狗蛋 10点钟输入账号密码登陆了银行网站
银行网站产生了Cookie 信息发送给浏览器保持链接(HTTP是无状态的,对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,两种用于保持HTTP连接状态的技术就应运而生了,一个是Cookie,而另一个则是Session),此时狗蛋就登陆成功了就可以正常向银行发送请求了。
然后狗蛋没有退出登陆的银行网站,在浏览器又打开了一个李四建立的黄色网站观看小片,李四通过这个网站返回一些攻击性代码获取到狗蛋的Cookie 信息,携带这些信息,通过浏览器发送请求给银行网站,获得正常权限,李四利用狗蛋的权限进行了转账操作。等到狗蛋发现钱少了去查银行信息,信息提示确实是他本人操作的。

Django 有一个专门针对CSRF 的解决办法:那就是在生成的每一个表单中放置一个自动生成的令牌,针对这个令牌判断Post请求是否来自同一个网站,。 我们使用模板标签添加令牌。{%csrf_token %} 。

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

运行,显示了一个空白列表。,因为我们还没设置acthion = 属性, 提示他把表单提交给那个URl处理,url 会找到对应的视图函数处理这个post 请求,这也意味着我们需要写一个单元测试。
在这里插入图片描述
打开 tests,在HomePageTest类中添加新方法

def test_can_save_a_POST_request(self):
      response = self.client.post("/",data = {'item_text':'A new list item'})
      #指定要发送的表单数据 data  对应 url /
      self.assertIn('A new list item ',response.content.decode())
     断言检查自己发送的Post请求渲染到Html 是否是制定的 data 数据

符合预期失败了,因为我们的 / url 对应的函数中根本没有 传入键值 item_text
在这里插入图片描述
现在在 home_page 中添加 语句
if request.method == ‘POST’
return HttpResponse(request.POST[‘item_text’])
return render(request,‘home.html’)
运行成功解决问题。
虽然单元测试通过了但是结果并不满意,因为我们要实现的效果是把post 请求提交的数据渲染在首页表格里
要实现这个功能 我们需要 把python 变量传入模板中渲染
在这里要去了解一一下 Django 模板语法
使用{{…}} 他会以字符串的形式显示对象。
我们写一下测试运行,

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

测试是成功的他显示了,但是观看他打开的页面他打开了俩
我们调整一下单元测试,检查是否还是在home.html,
结果显然是失败的。
在这里插入图片描述
我们需要重写视图函数,把Post 请求中的参数传入模板。render 函数的第三个参数是一个字典,把变量名映射到模板上

def home_page(request):
      return render(request,'home.html',{‘new_item_tex':request.POST['item_text'],})

结果 是失败了,可以看出是一个键值错误
在这里插入图片描述
因为: dict[‘key’]方法只能获取存在的值,如果不存在则触发KeyError
我们第一次渲染的时候并没有值,所以我们要改用 dic.get()方法
dict.get(key, default=None)则如果不存在则返回一个默认值,如果设置了则是设置的,否则就是None

def home_page(request):
      return render(request,'home.html',{‘new_item_tex':request.POST.get('item_text',' ')})

运行单元测试通过
运行功能测试查看结果:并没有太大帮助
在这里插入图片描述
作者提供了另外一种功能测试作为改进,这个可以协助调试以后出现的错误把这个更改一下
在这里插入图片描述
assertTrue改为

self.asssertIn('1:1:Buy woolen yarn',[row.text for row in rows])

运行之后
在这里插入图片描述
模板中获取的跟我们希望显示的不一样呢
添加进去再测一下看是否正确

1:{{new_item_text}} 结果当然是我们成功了,但是这种做法是作弊的,我们使用了常量1:,无疑是把他写死了。 在这里作者向我们提出了一些概念特别重要 单元测试/编写代码 循环有时候也叫 遇红/变绿/重构 和三角法

1. 先写一个会失败的测试(遇红)
2. 编写尽可能可以通过的代码(遇绿),就算作弊也行
3. 改进代码,让他合理(重构)
如何判断什么时候应该把作弊的代码改变成满意的实现方式呢:

方法一消除重复 如果测试中使用了神奇常量,而应用代码中也使用了这个常量,这就算重复,此时就应该重构。
方法二 三角法 如果编写无法让你满意的作弊代码(例如返回一个神奇常量)就能让你的测试通过,就再编写一个测试,强制自己写更好的代码。

现在我们来使用三角法扩充功能测试,检查输入的第二个列表项目是否包含2
添加第二个代办事件

#页面中又显示了一个文本框,可以输入其他待办事项
#她输入了"Knit a sweater with wool”(使用毛线织毛衣)
        inputbox.send_keys("Knit a sweater with wool")
        inputbox.send_keys(Keys.ENTER)
        time.sleep(1)
#页面再次跟新,他的清单中显示了这两个待办事项
# 待办事项中显示  1:Buy woolen yarn
#                 2:Knit a sweater with wool
        table = self.browser.find_element_by_id('id_list_table')
        rows  = table.find_elements_by_tag_name('tr')
        self.assertIn(
          "1:Buy woolen yarn",[row.text for row in rows])
        self.assertIn(
          "2:Knit a sweater with wool",[row.text for row in rows])
        self.fail("Finish the test")

结果显示这样的错误:selenium.common.exceptions.StaleElementReferenceException: Message: The element reference of is stale; either the element is no longer attached to the DOM, it is not in the current frame context, or the document has been refreshed
在这里插入图片描述
我没有定位这个元素修那就定位一下

#页面中又显示了一个文本框,可以输入其他待办事项
#她输入了"Knit a sweater with wool”(使用毛线织毛衣)
        inputbox = self.browser.find_element_by_id('id_new_item')  忘了写他
        inputbox.send_keys("Knit a sweater with wool")
        inputbox.send_keys(Keys.ENTER)
        time.sleep(1)
#页面再次跟新,他的清单中显示了这两个待办事项
# 待办事项中显示  1:Buy woolen yarn
#                 2:Knit a sweater with wool
        table = self.browser.find_element_by_id('id_list_table')
        rows  = table.find_elements_by_tag_name('tr')
        self.assertIn(
          "1:Buy woolen yarn",[row.text for row in rows])
        self.assertIn(
          "2:Knit a sweater with wool",[row.text for row in rows])
        self.fail("Finish the test")

结果:很显然不正确,也证明了我们的作弊方法不正确。
在这里插入图片描述
下一章见

猜你喜欢

转载自blog.csdn.net/weixin_43147867/article/details/86540749
5.1
今日推荐