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

相关推荐
山人在山上9 分钟前
arcgis server ip修改后服务异常解决方案
数据库·tcp/ip·arcgis
不剪发的Tony老师31 分钟前
SQL实现新年倒计时功能
数据库·sql
小小药38 分钟前
009-spring-bean的实例化流程
java·数据库·spring
DashVector1 小时前
如何通过HTTP API插入或更新Doc
大数据·数据库·数据仓库·人工智能·http·数据库架构·向量检索
hac13221 小时前
瀚高数据库
数据库
小小小妮子~1 小时前
深入理解 MySQL 架构
数据库·mysql·架构
man20172 小时前
【2024最新】基于Python+Mysql+django的水果销售系统Lw+PPT
数据库·mysql·django
度假的小鱼2 小时前
01 Oracle 基本操作
数据库·oracle
张声录12 小时前
【ETCD】【实操篇(十)】基于 ETCD 实现一个简单的服务注册及发现功能
数据库·etcd
张声录12 小时前
【ETCD】【实操篇(十八)】ETCD监控实战:提升系统健康与集群调试效率
数据库·chrome·etcd