5. 视图——Django

1. 编写更多视图
(python3.8) [root@node8 polls]# pwd
/blueicex/python-project/mysite/polls
(python3.8) [root@node8 polls]# vim views.py 

from django.shortcuts import render
from django.http import HttpResponse
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(response % question_id)

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

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

添加路由

(python3.8) [root@node8 polls]# pwd
/blueicex/python-project/mysite/polls
(python3.8) [root@node8 polls]# vim urls.py 
from django.urls import path
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'),
]
2. 写一个真正有用的视图

每个视图必须要做的只有两件事:返回一个包含被请求页面内容的 HttpResponse 对象,或者抛出一个异常,比如 Http404 。
视图可以从数据库里读取记录,可以使用一个模板引擎(比如 Django 自带的,或者其他第三方的),可以生成一个 PDF 文件,可以输出一个 XML,创建一个 ZIP 文件。
Django 只要求返回HttpResponse ,或者抛异常。

(python3.8) [root@node8 polls]# vim views.py 
from django.shortcuts import render
from django.http import HttpResponse
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(response % question_id)

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

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)

页面的设计写死在视图函数的代码里

3. 模板

在 polls 目录里创建 templates 目录。Django 会在templates 目录里查找模板文件。

项目的 TEMPLATES 配置项描述了 Django 如何载入和渲染模板。默认的设置文件设置了 DjangoTemplates 后端,并将 APP_DIRS 设置成了 True。这一选项将会让 DjangoTemplates 在每个 INSTALLED_APPS 文件夹中寻找 “templates” 子目录。这就是为什么尽管没有像在第二部分中那样修改 DIRS 设置,Django 也能正确找到 polls 的模板位置的原因。
在创建的 templates 目录里,再创建一个目录 polls,新建一个文件 index.html 。因为app_directories模板加载器是通过上述描述的方法运行的,所以Django可以引用到 polls/index.html 模板了。

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

更新polls/views.py 里的 index 视图使用模板
vim views.py

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]
    template = loader.get_template('polls/index.html')
    context = {
        'latest_question_list': latest_question_list,
    }
    return HttpResponse(template.render(context, request))

载入 polls/index.html 模板文件,并且向它传递上下文(context)。上下文是一个字典,它将模板内的变量映射为 Python 对象。

4. 快捷函数 render()
vim views.py
from django.shortcuts import render
from .models import Question
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)

不再需要导入 loader 和 HttpResponse

5. 抛出 404 错误
vim views.py
from django.http import Http404
from django.shortcuts import render
from .models import Question
# ...
def detail(request, question_id):
    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})
6. 快捷函数 get_object_or_404()

尝试用 get() 函数获取一个对象,如果不存在就抛出 Http404 错误也是一个普遍的流程。Django 提供了一个快捷函数get_object_or_404()

vim views.py
from django.shortcuts import get_object_or_404, render

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

设计哲学
为什么使用辅助函数 get_object_or_404() 而不是自己捕获 ObjectDoesNotExist 异常呢?为什么模型 API 不直接抛出 ObjectDoesNotExist 而是抛出 Http404 呢?
因为这样做会增加模型层和视图层的耦合性。Django 设计的最重要的思想之一就是要保证松散耦合
也有 get_list_or_404() 函数,工作原理和 get_object_or_404() 一样,除了 get() 函数被换成了 filter() 函数。如果列表为空的话会抛出 Http404 异常。

7. 使用模板系统
vim 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>

在 {% for %} 循环中发生的函数调用:question.choice_set.all 被解释为 Python 代码 question.choice_set.all() ,将会返回一个可迭代的 Choice 对象,这一对象可以在 {% for %} 标签内部使用。

8. 去除模板中的硬编码 URL

在 polls/index.html 里编写投票链接时,链接是硬编码

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

硬编码和强耦合的链接,对于一个包含很多应用的项目来说,修改起来是十分困难的。在 polls.urls 的 url() 函数中通过 name 参数为 URL 定义了名字,使用 {% url %} 标签代替硬编码

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

在 polls.urls 模块的 URL 定义中寻具有指定名字的条目

...
# the 'name' value as called by the {% url %} template tag
path('<int:question_id>/', views.detail, name='detail'),
...

改变投票详情视图的 URL,比如想改成 polls/specifics/12/ ,不用在模板里修改任何东西,只要在 polls/urls.py 里稍微修改

...
# added the word 'specifics'
path('specifics/<int:question_id>/', views.detail, name='detail'),
...
9. 为 URL 名称添加命名空间

在根 URLconf 中添加命名空间,加上 app_name 设置命名空间。

vim polls/urls.py
from django.urls import path
from . import views

app_name = 'polls'
urlpatterns = [
    path('', views.index, name='index'),
    path('<int:question_id>/', views.detail, name='detail'),
    path('<int:question_id>/results/', views.results, name='results'),
    path('<int:question_id>/vote/', views.vote, name='vote'),
]
vim 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>

————Blueicex 2020/07/20 22:41 blueice1980@126.com

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值