django (六) 第一个django app 创建views
在Django,网页和其他内容通过views来进行交互。每个视图都通过一个简单的Python函数(或方法)来展示。Django将通过检查请求的URL来选择一个视图(更精确地说是域名后面的URL)。从URL到View的过程是通过URLconfs来控制的。
接下来让我们写一个view。首先打开polls/views.py,添加如下代码:
# -*- coding: utf-8 -*- from django.http import HttpResponse def index(request): return HttpResponse("Hello, world. You’re at the poll index.")
接下来打开在polls文件夹下新建一个urls.py文件,建立view和url的联系,代码如下:
# -*- coding: utf-8 -*- from django.conf.urls import patterns, url from polls import views urlpatterns = patterns('', url(r'^$', views.index, name='index') )
然后打开mysite/urls.py,添加代码如下:
urlpatterns = patterns('', url(r'^polls/', include('polls.urls')), url(r'^admin/', include(admin.site.urls)), )
注意一下,所有的html文件都要保存为utf-8格式。
现在你就有一个Poll的主页了,进入http://127.0.0.1:8000/polls/.
下面我们来分析一下这行代码:
url(r'^$', views.index, name='index')
url有两个固定参数,正则表达式和view,另外还有两个可选的这里暂不做介绍。
接下来让我们在polls/view.py里添加更多的方法。不过和之前的有所不同,他们多了一个变量。代码如下:
# -*- coding: utf-8 -*- from django.http import HttpResponse def index(request): return HttpResponse("Hello, world. You’re at the poll index.") def detail(request, poll_id): return HttpResponse("You’re looking at poll %s." % poll_id) def results(request, poll_id): return HttpResponse("You’re looking at the results of poll %s." % poll_id) def vote(request, poll_id): return HttpResponse("You’re voting on poll %s." % poll_id)
然后在polls/url.py里添加下面的代码:
import sys from django.conf.urls import patterns, url from polls import views reload(sys) sys.setdefaultencoding('utf-8') urlpatterns = patterns('', url(r'^$', views.index, name='index'), # ex: /polls/5/ url(r'(?P<poll_id>\d+)/$',views.detail,name='detail'), # ex: /polls/5/results/ url(r'^(?P<poll_id>\d+)/results/$', views.results, name='results'), # ex: /polls/5/vote/ url(r'^(?P<poll_id>\d+)/vote/$', views.vote, name='vote'), )
请在在网页里依次的试一试吧!
好的,下面我们将继续完善,首先修改polls/views.py的index方法,完整代码如下:
# -*- coding: utf-8 -*- from django.http import HttpResponse from polls.models import Poll def index(request): latest_poll_list = Poll.objects.order_by('-pub_date')[:5] output = ', '.join([p.question for p in latest_poll_list]) return HttpResponse(output) def detail(request,poll_id): return HttpResponse("You’re looking at poll %s." %poll_id) def results(request,poll_id): return HttpResponse("You’re looking at the results of poll %s." %poll_id) def vote(request,poll_id): return HttpResponse("You’re voting on poll %s." %poll_id)
Ok,页面变得不一样了,但是,这样修改外观时并不是很直观,为了使代码和外观分离,我们在template里面去改变它。
这里我们在polls目录下新建一个templates,在templates里再建一个目录polls,在他下面新建一个index.html。
polls/templates/polls/index.html.
编辑代码如下:
{% if latest_poll_list %} <ul> {% for poll in latest_poll_list %} <li><a href="/polls/{{ poll.id }}/">{{ poll.question }}</a></li> {% endfor %} </ul> {% else %} <p>No polls are available.</p> {% endif %}
然后重新修改polls/view.py如下:
# -*- coding: utf-8 -*- from django.http import HttpResponse from django.template import RequestContext, loader from polls.models import Poll def index(request): latest_poll_list = Poll.objects.order_by('-pub_date')[:5] template = loader.get_template('polls/index.html') context = RequestContext(request,{'latest_poll_list':latest_poll_list,}) return HttpResponse(template.render(context)) def detail(request,poll_id): return HttpResponse("You’re looking at poll %s." %poll_id) def results(request,poll_id): return HttpResponse("You’re looking at the results of poll %s." %poll_id) def vote(request,poll_id): return HttpResponse("You’re voting on poll %s." %poll_id)
效果如下:
context 和 render经常成双出现,下面介绍一种更简便的写法:
修改polls/view。py如下:
# -*- coding: utf-8 -*- from django.shortcuts import render from polls.models import Poll def index(request): latest_poll_list = Poll.objects.order_by('-pub_date')[:5] context = {'latest_poll_list':latest_poll_list,} return render(request, 'polls/index.html', context) def detail(request,poll_id): return HttpResponse("You’re looking at poll %s." %poll_id) def results(request,poll_id): return HttpResponse("You’re looking at the results of poll %s." %poll_id) def vote(request,poll_id): return HttpResponse("You’re voting on poll %s." %poll_id)
ok.接下来完成views.py下的另外几个功能,首先是根据指定polls的id号找到那个Poll,找不到会出现404错误,页面全部代码如下:
# -*- coding: utf-8 -*- from django.shortcuts import render from django.http import Http404 from polls.models import Poll def index(request): latest_poll_list = Poll.objects.order_by('-pub_date')[:5] context = {'latest_poll_list':latest_poll_list,} return render(request, 'polls/index.html', context) def detail(request, poll_id): try: poll = Poll.objects.get(pk=poll_id) except Poll.DoesNotExist: raise Http404 return render(request,'polls/detail.html', {'poll': poll}) def results(request,poll_id): return HttpResponse("You’re looking at the results of poll %s." %poll_id) def vote(request,poll_id): return HttpResponse("You’re voting on poll %s." %poll_id)
在polls下新建detail.html
这里暂时先临时写一个,往里面添加:
{{ poll }}
同样,关于404和get也有个简写组合,详细代码如下:
# -*- coding: utf-8 -*- from django.shortcuts import render, get_object_or_404 from polls.models import Poll def index(request): latest_poll_list = Poll.objects.order_by('-pub_date')[:5] context = {'latest_poll_list':latest_poll_list,} return render(request, 'polls/index.html', context) def detail(request, poll_id): poll = get_object_or_404(Poll, pk=poll_id) return render(request,'polls/detail.html', {'poll': poll}) def results(request,poll_id): return HttpResponse("You’re looking at the results of poll %s." %poll_id) def vote(request,poll_id): return HttpResponse("You’re voting on poll %s." %poll_id)
404的页面只能在根UROconf去加载,在各自的应用下加载无效。所以接下来在Root模板文件夹下(mysite/templates)新建404.html。
现在随便给404.html添加一些内容:
<h1>Page not found</h1> <p>Sorry, but the requested page could not be found.</p>
如果你的程序处于调试状态,那么404页面永远不会显示,取而代之只会显示traceback。想改变调试状态可以在setting.py里去修改(第一行代码就是)。
DEBUG = False
注意一旦你关闭DEBUG模式,你必须给ALLOWED_HOSTS变量指定特定的值,这个根据需要而定,这里暂时设为:
ALLOWED_HOSTS = ['127.0.0.1']
接下来,我们写一个500(server error)的界面,同上,在相同位置创建一个500.html内容自己随便写。
之前我们的detail.html只显示poll的信息,没有具体的choice的信息,现在我们把它添加进去。编辑detail.html:
<h1>{{ poll.question }}</h1> <ul> {% for choice in poll.choice_set.all %} <li>{{ choice.choice_text }}</li> {% endfor %} </ul>
关于choice_set的解释请看这篇文章:
http://www.cnblogs.com/freeggache/articles/4441715.html
可以刷新页面,去看看效果。
现在来讨论一下这行代码:
<li><a href="/polls/{{ poll.id }}/">{{ poll.question }}</a></li>
这里/polls/属于hardcoded风格,摒弃,可以采取下面这种方式:
<li><a href="{% url 'detail' poll.id %}">{{ poll.question }}</a></li>
完整index.html的代码如下:
{% if latest_poll_list %} <ul> {% for poll in latest_poll_list %} <li><a href="{% url 'detail' poll.id %}">{{ poll.question }}</a></li> {% endfor %} </ul> {% else %} <p>No polls are available.</p> {% endif %}
这样的话,如果你以后想修改URL比如说polls/specifics/12/你不用在模板里面去修改,你只需要在polls/urls.py离去修改:
... # added the word 'specifics' url(r'^specifics/(?P<poll_id>\d+)/$', views.detail, name='detail'), ...
现在,我们polls应用程序已经搭建起来了,那么如何区分polls应用程序和其他应用程序的url呢?就比如上面的detail,为了解决这个问题,django引进了namespace,首先修改你的mysite/urls.py:
# -*- coding: utf-8 -*- from django.conf.urls import patterns, include, url from django.contrib import admin admin.autodiscover() urlpatterns = patterns('', url(r'^polls/', include('polls.urls', namespace="polls")), url(r'^admin/', include(admin.site.urls)), )
然后修改polls/index.html模板如下:
{% if latest_poll_list %} <ul> {% for poll in latest_poll_list %} <li><a href="{% url 'polls:detail' poll.id %}">{{ poll.question }}</a></li> {% endfor %} </ul> {% else %} <p>No polls are available.</p> {% endif %}