美文网首页
第一个Django App(三)

第一个Django App(三)

作者: 小桥流水啦啦啦 | 来源:发表于2020-03-08 11:07 被阅读0次

视图 views

在博客应用中,有下列视图:

博客homepage - 显示最近几个词条。

词条“detail”页 - 单个词条的永久连接页。

基于年份的存档页

基于月份的存档页

基于天的存档页

评论

在poll应用中,有下列4个视图:

Question ‘index’ page

Question 'detail' page

Question 'results' page

Vote action

Django中,web页及其他内容通过视图传递。每个视图由一个简单Python函数(或者方法,基于类的视图实例)表示。Django通过检查请求的URL来选择一个视图(为了更精准,URL部分在域名之后)。

为了从URL获取视图,Django采用‘URLconfs’。 URLconfs映射URL模式到视图。

写更多的视图 Writing more views

编辑polls/views.py

from django.shortcuts import render

Create your views here.

from django.http import HttpResponse

def index(request):
return HttpResponse("hello, world. You're at the polls index.")

def detail(request,question_id):
return HttpResponse("You're looking at Question %s." %question_id)

def results(request,question_id):
response = "You're looking at the results of question %s."
return HttpResponse(request % question_id)

def vote(request,question_id):
return HttpResponse("You're voting on question %s." %question_id)

编辑polls/urls.py

from django.urls import path

from django.conf.urls import url

from . import views

urlpatterns = [

ex: /polls/

path('',views.index,name='index'),

ex: /polls/5/

path('<int:question_id>/',views.detail,name='detail'),

ex: /polls/5/results/

path('<int:question_id>/results/',views.results,name='results'),

ex: /polls/5/vote/

path('<int:question_id>/vote/',views.vote,name='vote'),
]

运行测试:

root@imhqq-Lenovo-H5050:/home/imhqq/share/django_dev/mysite# python manage.py runserver
Performing system checks...

System check identified no issues (0 silenced).
December 30, 2017 - 15:19:37
Django version 2.0, using settings 'mysite.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.

Write views that actually do something

每个视图负责做一到两件事:返回一个包含请求页内容的HttpResponse对象,或者弹出一个Http404异常。

视图可以从从数据库读记录。视图也可以使用模板系统,比如说Django的,或者第三方Python模板系统。

视图也可以凭空生成一个PDF文件,输出XML,生成一个ZIP文件,任何你想要的,使用你想要的任何Python库。

编辑polls/views.py

from django.shortcuts import render

Create your views here.

from django.http import HttpResponse

from .models import Question

def index(request):
latest_question_list = Question.objects.order_by('-pub_date')[:5]
output = ', '.join([q.question_text for q in latest_question_list])
return HttpResponse(output)

def detail(request,question_id):
return HttpResponse("You're looking at Question %s." %question_id)

def results(request,question_id):
response = "You're looking at the results of question %s."
return HttpResponse(request % question_id)

def vote(request,question_id):
return HttpResponse("You're voting on question %s." %question_id)

上述视图是硬编码。如果想要改变网页显示的方式,将不得不编辑Python代码。使用创建的视图可以使用的Django模板系统来从Python中分离设计。

Django创建用户模板

首先,在polls下创建一个templates文件。

默认mysite/settings.py中,TEMPLATES的设置APP_DIRS为True.

TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,

为方便起见,DjangoTemplates在每个INSTALLED_APPS中搜索“templates”的子路径。

在创建的templates路径下,创建另一个称为polls的路径,在polls下创建一个index.html文件。也就是说,模板在polls/templates/polls/index.html下。在Django内部,可通过polls/index.html引用该模板。

编辑polls/templates/polls/index.html

{% if latest_question_list %}
<ul>
{% for question in latest_question_list %}
<li><a href="/poll/{{ question.id}}/">{{ question.question_text }}></a></li>
{% endfor %}
</ul>
{% else %}
<p>No polls are available.</p>
{% endif %}

在polls/views.py中更新index视图使用模板。

编辑polls/views.py文件

from django.shortcuts import render

Create your views here.

from django.http import HttpResponse

from django.template import loader

from .models import Question

def index(request):
latest_question_list = Question.objects.order_by('-pub_date')[:5]

add for using template 2017-12-30

template = loader.get_template('polls/index.html')

context = {'latest_question_list':latest_question_list}

return HttpResponse(template.render(context,request))

去掉下面这些硬编码

output = ', '.join([q.question_text for q in latest_question_list])

return HttpResponse(output)

使用render重写,使用render载入模板,不再需要使用loader及HttpResponse了。

context = {'latest_question_list':latest_question_list}
return render(request,'polls/index.html',context)

代码载入polls/index.html模板,并传入一个context。这个context对Python对象而言是一个字典映射模板变量名。

快捷方式:render():

render()是载入模板的通常用法,填充context并返回一个HttpResponse对象作为提供模板的结果。代码修改如上。

这样不再需要import loader和HttpResponse了。

render()函数采用request对象作为第一个入参,模板名字作为第二个入参,字典作为可选第三个入参。

返回一个由指定模板提交指定context而来的HttpResponse对象。

弹出404错误

处理detail视图的问题 - 为指定poll显示question context页面。

编辑polls/views.py

ef detail(request,question_id):

下面的硬编码删除

return HttpResponse("You're looking at Question %s." %question_id)

处理Http404错误

try:
question = Question.objects.get(pk=question_id)
except Question.DoesNotExist:
raise Http404("Question does not exist")
return render(request,'polls/detail.html',{'question':question})

编辑polls/templates/polls/detail.html

{{ question }}

快捷方式: get_object_or_404()

重写detail()视图

编辑polls/views.py

from django.shortcuts import get_object_or_404

def detail(request,question_id):

下面的硬编码删除

return HttpResponse("You're looking at Question %s." %question_id)

处理Http404错误

try:

question = Question.objects.get(pk=question_id)

except Question.DoesNotExist:

raise Http404("Question does not exist")

采用快捷方式重写

question = get_object_or_404(Question,pk=question_id)
return render(request,'polls/detail.html',{'question':question})

采用模板系统

编辑polls/templates/polls/detail.html

<h1>{{ question.question_text }}</h1>
<ul>
{% for choice in question_choice_set.all %}
<li>{{ choice.choice_text}}</li>
{% endfor %}
</ul>

上述模板系统采用.查找语法访问变量属性,在例子{{question.question_text}}中,首先Django对对象question做字典查找,失败之后在尝试属性查找。如果属性查找失败,尝试list-index查找。

移除模板中的硬编码URLs

模板中的硬编码示例:

<li><a href="/polls/{{ question.id }}/">{{ question.question_text }}</a></li>
对于这种硬编码,紧耦合方法,当改变项目中的多个模板的URLs时将带来许多问题。

考虑到在path()函数中的polls.urls模块中已经定义了名字参数,可以通过如下方法移除模板中的硬编码。

<li><a href="{% url 'detail' question.id %}">{{ question.question_text }}</a></li>
这是通过查找polls.urls模块中的URL定义的方式实现的。

在polls/urls.py中:

path('<int:question_id>/',views.detail,name='detail'),

如果想要改变detail的URL到/polls/specifies/12/,那么要改变/polls/urls.py如下:

path('/specifics/<int:question_id>/',views.detail,name='detail'),

Namespacing URL names

解决一个项目中多个app的问题,如何区分这些app之间的URL名字?例如,polls app有一个detail视图,另一个app也有一个detail视图。解决办法是在URLconf中增加命名空间。

编辑polls/urls.py

from django.urls import path

from django.conf.urls import url

from . import views
app_name = 'polls'
urlpatterns = [

ex: /polls/

path('',views.index,name='index'),

ex: /polls/5/

path('<int:question_id>/',views.detail,name='detail'),

ex: /polls/5/results/

path('<int:question_id>/results/',views.results,name='results'),

ex: /polls/5/vote/

path('<int:question_id>/vote/',views.vote,name='vote'),
]

同时修改/polls/templates/polls/index.html,在这个文件中指出命名空间细节。

原先:

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

修改为:

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

相关文章

网友评论

      本文标题:第一个Django App(三)

      本文链接:https://www.haomeiwen.com/subject/gxhddhtx.html