Django(5)-视图函数和模板渲染

Django 中的视图的概念是「一类具有相同功能和模板的网页的集合」

在我们的投票应用中,我们需要下列几个视图:

问题索引页------展示最近的几个投票问题。

问题详情页------展示某个投票的问题和不带结果的选项列表。

问题结果页------展示某个投票的结果。

投票处理器------用于响应用户为某个问题的特定选项投票的操作。

在 Django 中,网页和其他内容都是从视图派生而来。每一个视图表现为一个 Python 函数(或者说方法,如果是在基于类的视图里的话)。Django 将会根据用户请求的 URL 来选择使用哪个视图

添加视图

polls/view.py

python 复制代码
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)

这段代码是一个基本的 Django 视图函数,它接受一个 HTTP 请求对象 request 和一个 question_id 参数,然后返回一个 HTTP 响应。

  • HttpResponse 是 Django 提供的一个用于构建 HTTP 响应的类。
  • response 是一个字符串,其中包含了一个占位符 %s,用于展示 question_id 的值。
  • 通过 % 运算符,将 question_id 的值插入到 response 字符串中,形成最终的响应内容。
  • 最后,用 return 语句返回该响应对象。

添加url

polls/urls.py

python 复制代码
from django.urls import path
from . import views
urlpatterns=[
    path("",views.index,name="index"),
    path("<int:question_id>/",views.detail,name="detail"),
    path("<int:question_id>/results",views.detail,name="detail"),
    path("<int:question_id>/vote",views.detail,name="detail"),
]

运行并访问

每个视图必须要做的只有两件事:返回一个包含被请求页面内容的 HttpResponse 对象,或者抛出一个异常,比如 Http404 。至于你还想干些什么,随便你。

你的视图可以从数据库里读取记录,可以使用一个模板引擎(比如 Django 自带的,或者其他第三方的),可以生成一个 PDF 文件,可以输出一个 XML,创建一个 ZIP 文件,你可以做任何你想做的事,使用任何你想用的 Python 库。

Django 只要求返回的是一个 HttpResponse ,或者抛出一个异常。

获取最近5个投票问题

修改视图,在index() 函数里插入了一些新内容,让它能展示数据库里以发布日期排序的最近 5 个投票问题,以空格分割

polls/view.py

python 复制代码
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)


# Leave the rest of the views (detail, results, vote) unchanged

使用模板

创建文件polls/templates/polls/index.html

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/view.py中index函数

python 复制代码
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 对象

也可以直接使用render方法,该方法将模板渲染。

python 复制代码
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)

latest_question_list 为对象列表,传给模板后,模板取出对象中的信息

查看效果

点击名称进入详情

抛出404错误

当访问到不存在的id时,可以抛出404错误

polls/view.py

python 复制代码
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})

创建polls/templates/polls/detail.html

html 复制代码
{{ question }}

快捷函数get_object_or_404

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

python 复制代码
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})

表单处理

poll/templates/polls/detailhtml

python 复制代码
<form action="{% url 'polls:vote' question.id %}" method="post">
{% csrf_token %}
<fieldset>
    <legend><h1>{{ question.question_text }}</h1></legend>
    {% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}
    {% for choice in question.choice_set.all %}
        <input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}">
        <label for="choice{{ forloop.counter }}">{{ choice.choice_text }}</label><br>
    {% endfor %}
</fieldset>
<input type="submit" value="Vote">
</form>

这个模板页面包含表单form,

添加url

polls/urls.py

python 复制代码
path("<int:question_id>/vote/", views.vote, name="vote"),

polls/view.py

python 复制代码
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import get_object_or_404, render
from django.urls import reverse

from .models import Choice, Question


# ...
def vote(request, question_id):
    question = get_object_or_404(Question, pk=question_id)
    try:
        selected_choice = question.choice_set.get(pk=request.POST["choice"])
    except (KeyError, Choice.DoesNotExist):
        # Redisplay the question voting form.
        return render(
            request,
            "polls/detail.html",
            {
                "question": question,
                "error_message": "You didn't select a choice.",
            },
        )
    else:
        selected_choice.votes += 1
        selected_choice.save()
        # Always return an HttpResponseRedirect after successfully dealing
        # with POST data. This prevents data from being posted twice if a
        # user hits the Back button.
        return HttpResponseRedirect(reverse("polls:results", args=(question.id,)))
 from django.shortcuts import get_object_or_404, render


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

如果id不存在,返回404,如果存在,则对应问题选票+1,投票后跳转result页面

polls/templates/polls/results.html

html 复制代码
<h1>{{ question.question_text }}</h1>

<ul>
{% for choice in question.choice_set.all %}
    <li>{{ choice.choice_text }} -- {{ choice.votes }} vote{{ choice.votes|pluralize }}</li>
{% endfor %}
</ul>

<a href="{% url 'polls:detail' question.id %}">Vote again?</a>

选中选项,点击vote,进入results页面。

代码:https://github.com/2504973175/mysite_django/tree/main

相关推荐
__风__16 分钟前
PostgreSQL kv(jsonb)存储
数据库·postgresql
Databend22 分钟前
Databend 产品月报(2025年6月)
数据库
Little-Hu1 小时前
QML TextEdit组件
java·服务器·数据库
保持学习ing3 小时前
day1--项目搭建and内容管理模块
java·数据库·后端·docker·虚拟机
宇钶宇夕4 小时前
EPLAN 电气制图:建立自己的部件库,添加部件-加SQL Server安装教程(三)上
运维·服务器·数据库·程序人生·自动化
爱可生开源社区4 小时前
SQLShift 重磅更新:支持 SQL Server 存储过程转换至 GaussDB!
数据库
贾修行5 小时前
SQL Server 空间函数从入门到精通:原理、实战与多数据库性能对比
数据库·sqlserver
傲祥Ax5 小时前
Redis总结
数据库·redis·redis重点总结
一屉大大大花卷6 小时前
初识Neo4j之入门介绍(一)
数据库·neo4j
周胡杰6 小时前
鸿蒙arkts使用关系型数据库,使用DB Browser for SQLite连接和查看数据库数据?使用TaskPool进行频繁数据库操作
前端·数据库·华为·harmonyos·鸿蒙·鸿蒙系统