Django入门笔记【三】

入门笔记翻译整理自:https://docs.djangoproject.com/en/1.8/

*该笔记将使用一个关于投票网络应用(poll application)的例子来阐述Django的用法。

Public interface - views.

1. 定义

视图(View)是Django应用中用于实现某一特定功能的Web页面。比如,一个博客可以有博客展示页面,博客创建页面,评论页面。

2. 视图示例

写入代码

1 #polls/views.py
2 
3 from django.http import HttpResponse
4 
5 def index(request):
6     return HttpResponse("Hello, world. You're at the polls index.")

为了调用视图,我们需要将它映射到一个URL上,因此在polls目录下创建urls.py,最终目录结构如图所示

1 polls/
2     __init__.py
3     admin.py
4     models.py
5     tests.py
6     urls.py
7     views.py

在polls/urls.py中添加以下代码

1 # polls/urls.py
2 
3 from django.conf.urls import url
4 
5 from . import views
6 
7 urlpatterns = [
8     url(r'^$', views.index, name='index'),
9 ]

将根目录中的URLconf定位至polls/urls中,使用include()方法:

1 # mysite/urls.py
2 
3 from django.conf.urls import include, url
4 from django.contrib import admin
5 
6 urlpatterns = [
7     url(r'^polls/', include('polls.urls')),
8     url(r'^admin/', include(admin.site.urls)),
9 ]

现在可以通过http://localhost:8000/polls/进入polls应用的视图。

url()方法有四个参数,必填两个:regex, view;选填两个:kwargs, name。其中,regex对模式(pattern)进行匹配,不区分GET和POST;完成匹配后,Django会调用view函数,并将HttpRequest和其他参数传入view函数中;kwargs将关键字参数传入view函数中;name可以对URL 命名

3. 更多视图示例

向polls/views.py中添加更多视图,和前面不同,这些视图需要接收参数

 1 # polls/views.py
 2 
 3 def detail(request, question_id):
 4     return HttpResponse("You're looking at question %s." % question_id)
 5 
 6 def results(request, question_id):
 7     response = "You're looking at the results of question %s."
 8     return HttpResponse(response % question_id)
 9 
10 def vote(request, question_id):
11     return HttpResponse("You're voting on question %s." % question_id)

将这些视图映射到polls.urls

 1 # polls/urls.py
 2 
 3 from django.conf.urls import url
 4 
 5 from . import views
 6 
 7 urlpatterns = [
 8     # ex: /polls/
 9     url(r'^$', views.index, name='index'),
10     # ex: /polls/5/
11     url(r'^(?P<question_id>[0-9]+)/$', views.detail, name='detail'),
12     # ex: /polls/5/results/
13     url(r'^(?P<question_id>[0-9]+)/results/$', views.results, name='results'),
14     # ex: /polls/5/vote/
15     url(r'^(?P<question_id>[0-9]+)/vote/$', views.vote, name='vote'),
16 ]

Django实现视图的逻辑如下,以用户访问"/polls/34/"为例:

首先,Django寻找'^polls/'的相应匹配;

然后,Django会剥离匹配的字符串"polls/",同时将剩下的文本"34/"发送至'polls.urls';

最后,在'polls.urls'的URLconf中进一步匹配r'^(?P<question_id>[0-9]+)/$',并调用detail()视图。

4. 视图再举例

每一个视图都必须完成两个事件之一:返回HttpResponse,或者Http404。其余取决于应用需求。

 1 # polls/views.py
 2 
 3 from django.http import HttpResponse
 4 
 5 from .models import Question
 6 
 7 def index(request):
 8     latest_question_list = Question.objects.order_by('-pub_date')[:5]
 9     output = ', '.join([p.question_text for p in latest_question_list])
10     return HttpResponse(output)
11 # Leave the rest of the views (detail, results, vote) unchanged

但是这里有一个问题,视图页面是硬编码的(hard-coded)。推荐将模板和Python代码独立。

首先,创建polls/templates目录。Django会在该目录下寻找模板。TEMPLATES设置中的默认后台DjangoTemplates会在每个INSTALLED_APP下寻找templates子目录。

然后,创建polls/templates/polls/index.html。这里创建第二个polls子目录的目的在于,区分不同应用下相同名称的index.html文件。

接着,修改index.html文件

 1 # polls/templates/polls/index.html
 2 
 3 {% if latest_question_list %}
 4     <ul>
 5     {% for question in latest_question_list %}
 6         <li><a href="/polls/{{ question.id }}/">{{ question.question_text }}</a></li>
 7     {% endfor %}
 8     </ul>
 9 {% else %}
10     <p>No polls are available.</p>
11 {% endif %}

最后,修改polls/views.py文件

 1 # polls/views.py
 2 
 3 from django.http import HttpResponse
 4 from django.template import RequestContext, loader
 5 
 6 from .models import Question
 7 
 8 
 9 def index(request):
10     latest_question_list = Question.objects.order_by('-pub_date')[:5]
11     template = loader.get_template('polls/index.html')
12     context = RequestContext(request, {
13         'latest_question_list': latest_question_list,
14     })
15     return HttpResponse(template.render(context))

该代码加载polls/index.html,并将context传递给它。Context是映射模板变量到Python对象的字典。

render()方法可以简化代码

 1 # polls/views.py
 2 
 3 from django.shortcuts import render
 4 
 5 from .models import Question
 6 
 7 
 8 def index(request):
 9     latest_question_list = Question.objects.order_by('-pub_date')[:5]
10     context = {'latest_question_list': latest_question_list}
11     return render(request, 'polls/index.html', context)

5. 抛出404错误

通过detail视图来示范实现

 1 # polls/views.py
 2 
 3 from django.http import Http404
 4 from django.shortcuts import render
 5 
 6 from .models import Question
 7 # ...
 8 def detail(request, question_id):
 9     try:
10         question = Question.objects.get(pk=question_id)
11     except Question.DoesNotExist:
12         raise Http404("Question does not exist")
13     return render(request, 'polls/detail.html', {'question': question})

同时对polls/detail.html进行修改

1 # polls/templates/polls/detail.html
2 
3 {{ question }}

使用get_object_or_404()进行代码简化

1 #polls/views.py
2 
3 from django.shortcuts import get_object_or_404, render
4 
5 from .models import Question
6 # ...
7 def detail(request, question_id):
8     question = get_object_or_404(Question, pk=question_id)
9     return render(request, 'polls/detail.html', {'question': question})

 6. 使用模板系统

考虑context变量,对polls/detail.html进行修改

1 # polls/templates/polls/detail.html
2 
3 <h1>{{ question.question_text }}</h1>
4 <ul>
5 {% for choice in question.choice_set.all %}
6     <li>{{ choice.choice_text }}</li>
7 {% endfor %}
8 </ul>

7. 移除模板中的硬编码URL

比如polls/index.html,原代码不利于修改:

1 <li><a href="/polls/{{ question.id }}/">{{ question.question_text }}</a></li>

改进为:

1 <li><a href="{% url 'detail' question.id %}">{{ question.question_text }}</a></li>

这样改进过后,对URL的修改会变得很容易,比如,把以下代码

1 ...
2 # the 'name' value as called by the {% url %} template tag
3 url(r'^(?P<question_id>[0-9]+)/$', views.detail, name='detail'),
4 ...

改为

1 ...
2 # added the word 'specifics'
3 url(r'^specifics/(?P<question_id>[0-9]+)/$', views.detail, name='detail'),
4 ...

8. URL命名空间

一个项目里往往有很多应用,如果两个应用都有叫做detail的视图,Django会怎么区分它们的URL名称呢?答案是mysite/urls.py中可以添加命名空间到URLconf。比如:

1 # mysite/urls.py
2 
3 from django.conf.urls import include, url
4 from django.contrib import admin
5 
6 urlpatterns = [
7     url(r'^polls/', include('polls.urls', namespace="polls")),
8     url(r'^admin/', include(admin.site.urls)),
9 ]

同时将polls.index.html从

1 # polls/templates/polls/index.html
2 
3 <li><a href="{% url 'detail' question.id %}">{{ question.question_text }}</a></li>

修改为

1 # polls/templates/polls/index.html
2 
3 <li><a href="{% url 'polls:detail' question.id %}">{{ question.question_text }}</a></li>

--The End--

原文地址:https://www.cnblogs.com/py-drama/p/4582034.html