1. Django1.9应用特性注意事项
2016-07-07 21:04
453 查看
Django1.9抛弃了很多之前版本中的函数,也引入了一部分新的特性。下面主要来谈一下博主在Django1.9.x版本下开发应用过程中遇到的问题,以及一些注意事项。
Code.1
旧版本Django获取urlpatterns 方法代码示意:
Code.2
新方法还提供了面向对象的方法
Code.3
新方法用IndexView.as_view(),DetailView.as_view(),以及ResultsView.as_view(),通过在views.py中引入了generic (from django.views import generic ) 方法实现用对象配置url的功能替代views.py文件中函数对URL配置管理,新方法体现了Django在面向对象编程的特性。polls/views.py代码如下,其中注释部分代码为执行Code.1所用新代码为之前功能的:
Code.4
注意事项:
vs
在视图模式中question_id要变为pk,否则不仅涉及改变相关URL解析不会成功,还会影响到整个应用的url配置管理的实现。
**
阿里的工程师志向在博客写有价值的单元测试中提到的错误恒定定律(程序员的错误产出比是个常数)和规模代价平方定律(定位并修复一个BUG所需的代价正比于目标代码规模的平方)充分说明了单元测试对于软件项目质量保证的重要性。当我们在学习任何一种新的开发语言时候,任何没有UT代码的demo都是不完整的。在UT支持这方面,Django显然走在了前列,通过调用核心模块的TestCase(from django.test import TestCase)功能,我们很容易对开发中的Django应用写Uint Test代码。
Demo应用polls的UT代码如下:
Code.5
在Django框架下跑单元测试代码,所在路径为项目toger目录,polls应用(app)目录同级,上述代码单元测试运行结果如下:
表明10个单元测试的case全部通过。
更改单元测试代码Code.5最后的一行,使 status_code=404观察不通过的情况,提示如下:
单元测试报错代码会提示涉及Unit Test代码的位置,以及其他的一些有提示指向功能的报错信息。根据相关信息,我们可以更好地改善发现bug,在开发阶段保证得到高质量的代码。
参考资料:
1、Django1.9.x Document(PDF)
2、写有价值的单元测试
URL文件管理配置
Django1.9在URLConf的方面,引入url函数替代了之前的 patterns函数的功能,目前多数参考书籍关于urlpatterns值的获取还停留在patterns函数阶段,基本上没有对1.9版本中获取函数变为url的方法进行跟进介绍。 新的url函数在应用polls中URL配置文件如下,分别展示了url层级陪陪获取的方法。在新方法中每一个url匹配都被引入到了列表urlpatterns,替代了之前所用的元组urlpatterns。
Code.1
polls/urls.py from django.conf.urls import url from . import views urlpatterns = [ # ex: /polls/ url(r'^$', views.index, name='index'), # ex: /polls/5/ url(r'^(?P<question_id>[0-9]+)/$', views.detail, name='detail'), # ex: /polls/5/results/ url(r'^(?P<question_id>[0-9]+)/results/$', views.results, name='results'), # ex: /polls/5/vote/ url(r'^(?P<question_id>[0-9]+)/vote/$', views.vote, name='vote'), ]
旧版本Django获取urlpatterns 方法代码示意:
Code.2
polls/urls.py urlpatterns = patterns('', url(r'^article$','news_index' ,name="myarticle"), )
新方法还提供了面向对象的方法
Code.3
urlpatterns = [ # ex: /polls/ url(r'^$',views.IndexView.as_view(), name= 'index'), # ex: /polls/5/ url(r'^(?P<pk>[0-9]+)/$',views.DetailView.as_view(), name= 'detail'), # ex: /polls/5/results/ url(r'^(?P<pk>[0-9]+)/results/$',views.ResultsView.as_view(), name= 'results'), # ex: /polls/5/vote/ url(r'^(?P<question_id>[0-9]+)/vote/$',views.vote, name= 'vote'), ] --
新方法用IndexView.as_view(),DetailView.as_view(),以及ResultsView.as_view(),通过在views.py中引入了generic (from django.views import generic ) 方法实现用对象配置url的功能替代views.py文件中函数对URL配置管理,新方法体现了Django在面向对象编程的特性。polls/views.py代码如下,其中注释部分代码为执行Code.1所用新代码为之前功能的:
Code.4
from django.shortcuts import render, get_object_or_404 from django.http import HttpResponse, Http404, HttpResponseRedirect from django.core.urlresolvers import reverse from django.views import generic from django.utils import timezone from polls.models import Question, Choice # Create your views here. class IndexView(generic.ListView): template_name = 'polls/index.html' context_object_name = 'latest_question_list' def get_queryset(self): """ Return the last five published questions (not including those set to be published in the future). """ return Question.objects.filter( pub_date__lte=timezone.now() ).order_by('-pub_date')[:5] class DetailView(generic.DetailView): model = Question template_name = 'polls/detail.html' def get_queryset(self): """ Excludes any questions that aren't published yet. """ return Question.objects.filter(pub_date__lte=timezone.now()) class ResultsView(generic.DetailView): model = Question template_name = 'polls/results.html' #def index(request): # latest_question_list = Question.objects.order_by('-pub_date')[:5] # context = { # 'latest_question_list':latest_question_list, # } # return render(request, 'polls/index.html', context) # #def detail(request, question_id): # question = get_object_or_404(Question, pk= question_id) # return render(request, 'polls/detail.html', {'question': question}) # # #def results(request, question_id): # question = get_object_or_404(Question, pk=question_id) # return render(request, 'polls/results.html', {'question': question})
注意事项:
url(r'^(?P<question_id>[0-9]+)/$', views.detail, name='detail')
vs
url(r'^(?P<pk>[0-9]+)/$',views.DetailView.as_view(), name= 'detail'),
在视图模式中question_id要变为pk,否则不仅涉及改变相关URL解析不会成功,还会影响到整个应用的url配置管理的实现。
**
单元测试
**阿里的工程师志向在博客写有价值的单元测试中提到的错误恒定定律(程序员的错误产出比是个常数)和规模代价平方定律(定位并修复一个BUG所需的代价正比于目标代码规模的平方)充分说明了单元测试对于软件项目质量保证的重要性。当我们在学习任何一种新的开发语言时候,任何没有UT代码的demo都是不完整的。在UT支持这方面,Django显然走在了前列,通过调用核心模块的TestCase(from django.test import TestCase)功能,我们很容易对开发中的Django应用写Uint Test代码。
Demo应用polls的UT代码如下:
Code.5
import datetime from django.utils import timezone from django.test import TestCase from django.core.urlresolvers import reverse from polls.models import Question # Create your tests here. class QuestionMethodTests(TestCase): def test_was_published_recently_with_future_question(self): """ was_published_recently() should return False for questions whose pub_date is in the future. """ time = timezone.now() + datetime.timedelta(days=30) future_question =Question(pub_date=time) self.assertEqual(future_question.was_published_recently(),False ) def test_was_published_recently_with_old_question(self): """ was_published_recently() should return False for questions whose pub_date is older than 1 day. """ time = timezone.now() - datetime.timedelta(days=30) old_question =Question(pub_date=time) self.assertEqual(old_question.was_published_recently(),False ) def test_was_published_recently_with_recent_question(self): """ was_published_recently() should return True for questions whose pub_date is within the last day. """ time = timezone.now() - datetime.timedelta(hours=1) recent_question =Question(pub_date=time) self.assertEqual(recent_question.was_published_recently(), True ) def create_question(question_text, days): """ Creates a question with the given `question_text` and published the given number of `days` offset to now (negative for questions published in the past, postive for questions tha have yet to be published). """ time = timezone.now() + datetime.timedelta(days=days) return Question.objects.create( question_text=question_text, pub_date=time ) class QuestionViewTests(TestCase): def test_index_view_with_no_question(self): """ If no question exist, an appropriate message should be displayed. """ response = self.client.get(reverse('polls:index')) self.assertEqual(response.status_code, 200 ) self.assertContains(response, "No polls are available." ) self.assertQuerysetEqual(response.context['latest_question_list'], [] ) def test_index_view_with_a_past_question(self): """ Questions with a pub_date in the past should be displayed on the index page. """ create_question(question_text="Past question.", days=-30) response = self.client.get(reverse('polls:index')) self.assertQuerysetEqual( response.context['latest_question_list'], ['<Question: Past question.>'] ) def test_index_view_with_a_future_question(self): """ Questions with a pub_date in the future should no be displayed on the index page. """ create_question(question_text="Future question.", days=30) response = self.client.get(reverse('polls:index')) self.assertContains(response, "No polls are available.", status_code=200 ) self.assertQuerysetEqual(response.context['latest_question_list'], [] ) def test_index_view_with_future_question_and_past_question(self): """ Even if both past and future question exist, only past questions should be displayed. """ create_question(question_text="Past question.", days=-30) create_question(question_text="Future question.", days=30) response = self.client.get(reverse('polls:index')) self.assertQuerysetEqual( response.context['latest_question_list'], ['<Question: Past question.>'] ) def test_index_view_with_two_past_questions(self): """ The questions index page may display multiple questions. """ create_question(question_text="Past question 1.", days=-30) create_question(question_text="Past question 2.", days=-5) response = self.client.get(reverse('polls:index')) self.assertQuerysetEqual( response.context['latest_question_list'], ['<Question: Past question 2.>','<Question: Past question 1.>'] ) class QuestionIndexDetailTests(TestCase): def test_detail_view_with_a_future_question(self): """ The detail view of a question with a pub_date in the future should return a 404 not found. """ future_question = create_question(question_text="Future question.", days=5) response = self.client.get(reverse('polls:detail', args=(future_question.id,))) self.assertEqual(response.status_code, 404 ) def test_detail_view_with_a_past_question(self): """ The detail view of a question with a pub_date in the past should be display the question's text. """ past_question = create_question(question_text="Past question.", days=-5) response = self.client.get(reverse('polls:detail', args=past_question.id,))) self.assertContains(response,past_question.question_text, status_code=200)
在Django框架下跑单元测试代码,所在路径为项目toger目录,polls应用(app)目录同级,上述代码单元测试运行结果如下:
[hbu@localhost toger]$ python manage.py test polls Creating test database for alias 'default'... .......... ---------------------------------------------------------------------- Ran 10 tests in 0.043s OK Destroying test database for alias 'default'...
表明10个单元测试的case全部通过。
更改单元测试代码Code.5最后的一行,使 status_code=404观察不通过的情况,提示如下:
[hbu@localhost toger]$ python manage.py test polls Creating test database for alias 'default'... .F........ ====================================================================== FAIL: test_detail_view_with_a_past_question (polls.tests.QuestionIndexDetailTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/hbu/toger/polls/tests.py", line 130, in test_detail_view_with_a_past_question status_code=404) File "/usr/lib64/python2.7/site-packages/django/test/testcases.py", line 395, in assertContains response, text, status_code, msg_prefix, html) File "/usr/lib64/python2.7/site-packages/django/test/testcases.py", line 365, in _assert_contains " (expected %d)" % (response.status_code, status_code)) AssertionError: Couldn't retrieve content: Response code was 200 (expected 404) ---------------------------------------------------------------------- Ran 10 tests in 0.055s FAILED (failures=1) Destroying test database for alias 'default'...
单元测试报错代码会提示涉及Unit Test代码的位置,以及其他的一些有提示指向功能的报错信息。根据相关信息,我们可以更好地改善发现bug,在开发阶段保证得到高质量的代码。
参考资料:
1、Django1.9.x Document(PDF)
2、写有价值的单元测试
相关文章推荐
- java-用HttpURLConnection发送Http请求.
- VBScript 剪贴板抓取URL并在浏览器中打开
- Ruby单元测试框架TestUnit的替代者MiniTest介绍
- 用vbs 实现从剪贴板中抓取一个 URL 然后在浏览器中打开该 Web 站点
- asp获取URL参数的几种方法分析总结[原创]_应用技巧_脚本之家
- C#实现在网页中根据url截图并输出到网页的方法
- zend framework框架中url大小写问题解决方法
- url decode problem 解决方法
- php url地址栏传中文乱码解决方法集合
- 探讨:parse url解析URL,返回其组成部分
- C#实现自动识别URL网址的方法
- C#自定义针对URL地址的处理类实例
- JavaScritp添加url参数并将参数加入到url中及更改url参数的方法
- ASP让url的中文显示为编码
- 关于backbone url请求中参数带有中文存入数据库是乱码的快速解决办法
- JS使用ajax方法获取指定url的head信息中指定字段值的方法
- url中的特殊符号有什么含义(推荐)
- 关于URL中的特殊符号使用介绍
- JS来动态的修改url实现对url的增删查改
- js url传值中文乱码之解决之道