第一个Django App(三)


视图 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>





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值