当前位置: 首页>后端>正文

Django框架学习 - 创建视图

视图简介

视图在Django中的作用是用于处理Web请求信息以及返回响应信息的函数。
当我们访问http://127.0.0.1:8000/polls时,Django会解析出'polls'这个路径,然后拿着这个路径去URLconfs里配置相对应的视图函数,视图函数接收请求,然后处理请求,最后返回响应信息,也许这一段不是很理解,但是当做完之后再回头看,就很清楚了。

投票应用,需要列以下几个视图:

  • 问题索引页——展示最近的几个投票问题
  • 问题详情页——展示某个投票的问题和不带结果的选项列表
  • 问题结果页——展示某个投票的结果
  • 投票处理器——用于响应用户为某个问题的特定选项投票的操作

创建视图

增加视图

我们通过编辑polls/views.py来增加三个视图

# 创建问题详情页视图
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)

其中request属性,当一个页面被请求时,Django就会创建一个包含本次请求信息的HttpRequest对象,Django会将这个对象自动传递给视图函数,一般约定使用request参数来接收这个对象,在视图函数中,可以通过访问该对象的属性来提取http协议的的请求数据,以下是常用的属性,也可以查看【官网】中详细说明

request.GET:url上携带的参数,包含所有HTTP GET参数的字典对象QueryDict
request.POST:post请求携带的数据,包含所有HTTP POST参数的类字典对象QueryDict
request.method:请求方法,请求中使用的HTTP方法的字符串表示,全大写(POST/GET)
request.path:完整路径
request.path_info:URL的路径 不包含ip和端口 不包含参数
request.body:请求体

配置URLconfs

我们通过上面增加了polls/views.py的内容,但是我们还不能马上使用,因为当我们去访问的时候,Django并不能通过URL找到对应的视图函数,所以,我要在URLconfs里增加新增视图函数的路由,那来编辑一下polls/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'),
]

保存,重新运行Django。当然,我们可以根据上面路径上的注释来测试访问一下,即http://127.0.0.1:8000/polls/34http://127.0.0.1:8000/polls/34/resultshttp://127.0.0.1:8000/polls/34/vote,其实很简单的,是视图中question_id在接收path中的<int:question_id>,如果你不能清楚也没关系,后续将内容添加后,可以帮助更容易的理解。

使用视图

结合polls这个项目,我们给polls/views.py中的index视图函数进行修改一下,利用数据库API来查询和展示前五个投票问题

from django.http import HttpResponse
from .models import Question


def index(request):
    # 利用数据库API来获取前五个问题
    latest_question_list = Question.objects.order_by('-pub_date')[:5]
    # 将内容提取出来,使用','符号拼接起来
    output = ', '.join([q.question_text for q in latest_question_list])
    # 使用HttpResponse返回拼接后的内容
    return HttpResponse(output)

创建静态文件

上面的代码可以展示前五个问题,但是这时的展示是没有经过渲染的,所以我们给它们加上模板文件进行渲染,Django中提供了对应的寻找目录,即在polls下创建一个template文件夹,再在这个文件夹下创建一个polls的文件夹,最后在这个文件里创建index.html文件,完整的路径就是polls/template/polls/index.html,这个是在setting.py文件中TEMPLATES选项设置的。

然后,我们可以将以下内容,填充到刚创建的模板文件(polls/template/polls/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来使用模板渲染

from django.http import HttpResponse
from django.template import loader

from .models import Question


def index(request):
    # 利用数据库API来获取前五个问题
    latest_question_list = Question.objects.order_by('-pub_date')[:5]
    # 指定渲染使用的模板
    template = loader.get_template('polls/index.html')
    # 指定问题列表
    context = {
        'latest_question_list': latest_question_list,
    }
    # 将问题列表传到模板中,然后通过HttpResponse返回响应
    return HttpResponse(template.render(context, request))

快捷函数:render()

以上代码中,载入模板-填充模板上下文-生成HttpResponse对象,这一套流程使用太过于频繁,所以Django提供了一个render()函数来减少冗余,我们把上面的代码通过render()来重写

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)

抛出404

访问404,也是很常用的一个操作,当我们访问不存在的一个问题ID时,就抛出404异常

from django.http import Http404
from django.shortcuts import render
from .model import Question

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

此时,这个detail视图使用到了一个模板文件,但是我们没有创建,所以现在无法正常运行,我们先创建一个,进行占位,即polls/template/polls/detail.html

{{ question }}

快捷函数:get_object_or_404()

尝试使用get()函数获取一个对象,如果不存在就抛出Http404异常也是一个普遍的流程,对此,Django也提供了一个快捷函数,所以我们利用这个快捷函数来修改一个detail视图

from django.shortcuts import get_object_or_404, render
from .model import Question

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

优化模板

我们来补全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 }}
{ % for % }循环中发生的函数调用:question.choice_set.all被解释为Python代码中的question.choice_set.all(),将会返回一个可迭代的Choice对象,这个对象被for循环输出

去除硬编码

向上翻,可以看到polls/index.html中的投票链接是硬链接

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

这个问题在于,硬链接和强耦合相链接,对于一个包含多个应用的项目,修改起来比较复杂,所以我们可以使用在polls/urls.py中为URL定义的name参数来替代原有的硬链接,使用{ % url %}来使用

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

URL命名空间

命名空间的作用是,区分多个应用时,{% url %}中name参数对应哪条URL,修改比较简单,就是在polls/urls.py中添加app_name参数

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'),
]

所以还需要修改一下polls/index.html文件

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

https://www.xamrdz.com/backend/3b81923419.html

相关文章: