让浏览器发送POST请求,将《lists/templates/home.html》文件写为:
<html>
<head>
<title>To-Do lists</title>
</head>
<body>
<h1>Your To-Do lists</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">
{% for item in items %}
<tr><td>{{ forloop.counter }}: {{ item.text }}</td></tr>
{% endfor %}
</table>
</body>
</html>
首先,加入了form标签,指定了POST请求;{% csrf_token %}是为了解决CSRF漏洞;加入了可以实现多个事项保存的部分。
编写新的单元测试,《list/tests.py》中写入:
from django.test import TestCase
from django.core.urlresolvers import resolve
from .views import home_page
from django.http import HttpRequest
from django.template.loader import render_to_string
from .models import Item
# Create your tests here.
class HomePageTest(TestCase):
def test_root_url_resolve_to_home_page_view(self):
found = resolve('/')
self.assertEqual(found.func, home_page)
def test_home_page_returns_correct_html(self):
request = HttpRequest()
response = home_page(request)
self.assertTrue(response.content.startswith(b'<html>'))
self.assertIn(b'<title>To-Do lists</title>',response.content)
self.assertTrue(response.content.endswith(b'</html>'))
expected_html = render_to_string('home.html',request=request)
#f = open('recode.txt', 'w')
#f.write(response.content.decode())
#f.write('\n'+expected_html)
#因为构建了跨站请求使得这里不相等,利用正则表达式去掉CSRF的内容
import re
pattern1_str = re.compile(r'value=(.*?)</form>',re.S)
# result1_str = re.search(pattern1_str, response.content.decode())
# print('csrf==',result1_str)
response_content_decode_str_strip = re.sub(pattern1_str,"",response.content.decode())
pattern2_str = re.compile(r'value=(.*?)</form>', re.S)
# result2_str = re.search(pattern2_str, expected_html)
# print('csrf==', result2_str)
expected_html_str_strip = re.sub(pattern2_str, "", expected_html)
self.assertEqual(response_content_decode_str_strip, expected_html_str_strip)
def test_home_page_can_save_a_POST_requests(self):
request = HttpRequest()
request.method = 'POST'
request.POST['item_text'] = 'A new list item'
response = home_page(request)
self.assertEqual(Item.objects.count(),1)
new_item = Item.objects.first()
self.assertEqual(new_item.text, 'A new list item')
def test_home_page_redirects_after_POST(self):
request = HttpRequest()
request.method = 'POST'
request.POST['item_text'] = 'A new list item'
response = home_page(request)
self.assertEqual(response.status_code,302)
self.assertEqual(response['location'],'/')
def test_home_page_only_save_items_when_necessary(self):
request = HttpRequest()
home_page(request)
self.assertEqual(Item.objects.count(),0)
def test_home_page_displays_all_list_items(self):
Item.objects.create(text='itemey 1')
Item.objects.create(text='itemey 2')
request = HttpRequest()
response = home_page(request)
f=open('recode.txt','w')
f.write(response.content.decode())
f.close()
self.assertIn('itemey 1', response.content.decode())
self.assertIn('itemey 2', response.content.decode())
class ItemModelTest(TestCase):
def test_saving_and_retrieving_items(self):
first_item = Item()
first_item.text = 'The first(ever) list item'
first_item.save()
second_item = Item()
second_item.text = 'Item the second'
second_item.save()
saved_items = Item.objects.all()
self.assertEqual(saved_items.count(),2)
first_saved_item = saved_items[0]
second_saved_item = saved_items[1]
self.assertEqual(first_saved_item.text, 'The first(ever) list item')
self.assertEqual(second_saved_item.text, 'Item the second')
改写功能测试《functional.py》:
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import unittest
import time
class NewVisitorTest(unittest.TestCase):
def setUp(self):
# 给出webdriver的路径
drive_path = 'C:\Program Files (x86)\Google\Chrome\Application\chromedriver\chromedriver.exe'
# 这是为了忽略浏览器提示“正受到自动化软件的控制”
option = webdriver.ChromeOptions()
option.add_argument('disable-infobars')
self.browser = webdriver.Chrome(executable_path=drive_path, chrome_options=option)
self.browser.implicitly_wait(3)
def tearDown(self):
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])
def test_can_start_a_list_and_retrieve_it_later(self):
self.browser.get('http://localhost:8000')
self.assertIn('To-Do', self.browser.title)
header_text = self.browser.find_element_by_tag_name('h1').text
self.assertIn('To-Do',header_text)
#应用邀请他输入一个代办事项
inputbox = self.browser.find_element_by_id('id_new_item')
self.assertEqual(inputbox.get_attribute('placeholder'), 'Enter a to-do item')
inputbox.send_keys('Buy peacock feathers')
inputbox.send_keys(Keys.ENTER)
#她按了回车键之后页面更新了
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)
# 她按了回车键之后页面更新了
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('finish the test!')
if __name__ == '__main__':
unittest.main(warnings='ignore')
在模型《lists/models.py》中建立Item类:
from django.db import models
# Create your models here.
class Item(models.Model):
text = models.TextField(default='')
修改视图《lists/views.py》
from django.shortcuts import render,redirect
from django.http import HttpResponse
from .models import Item
# Create your views here.
from django.shortcuts import render
def home_page(request):
if request.method == 'POST':
Item.objects.create(text=request.POST['item_text'])
return redirect('/')
items = Item.objects.all()
return render(request,'home.html',{'items':items})
使用python manage.py makemigrations
创造迁移;
使用python manage.py migrate
创建数据库