Django教程:视图介绍及使用

Django是一个非常流行的Python Web框架,它允许开发者轻松构建强大的Web应用程序。上一篇文章中,我们介绍了Python的模型,以及模型相关的使用方法。在本文中,我将详细介绍Django视图的概念和用法,并通过一些示例代码来增强我们对Djang视图的理解。

视图是 Django 中处理 HTTP 请求和生成 HTTP 响应的函数或方法。它们负责处理用户的请求,并返回相应的内容。要创建视图,你需要定义一个函数或方法,并将其绑定到URL。

1.定义视图

首先,在Django项目的根目录下创建一个名为views.py的文件。在这个文件中,我们将定义我们的视图。

python 复制代码
# 在views.py中引入必要的模块
from django.shortcuts import render
from django.http import HttpResponse
from bbs import Post
# Create your views here.

def hello(request):
    return HttpResponse("Hello, Django !")

def get_post(request, title):
    # 从数据库中获取用户数据
    post= Post.objects.get(title=title)
    # 将数据传递给模板,渲染页面
    return render(request, 'post.html', {'post': post})

上面的代码示例中,我们定义了两个视图函数。第一个函数 hello 接收一个 request 对象,并返回一个简单的 HttpResponse 响应,其中包含 "Hello, Django!" 的文本。

第二个视图函数 get_post 接收两个参数:request 对象和 title,它从数据库中查询到与title相对应的用户数据,并将其传递给名为 post.html 的模板文件进行渲染。

2. URL映射

接下来,我们需要在 urls.py 文件中将这些视图映射到相应的URL。

python 复制代码
from django.urls import path
from . import views

urlpatterns = [
    path('hello/', views.hello, name='hello'),
    path('post/<str:title>/', views.title, name='get_post'),
]

在上面的代码中,我们使用 path 函数将URL映射到相应的视图函数。第一个URL模式将 hello/ 映射到 hello 视图函数。第二个URL模式将 post/ 后面的 title 部分传递给 get_post 视图函数。

3. 视图装饰器

Django提供了一些常用的视图装饰器,可以用于添加额外的功能或进行授权验证。

python 复制代码
from django.contrib.auth.decorators import login_required

@login_required
def protected_view(request):
    return HttpResponse("This view requires authentication.")

对于装饰器,目前我们只需要有个大致的了解,知道有这么个东西就行,后续内容中,会详细讲解装饰器的应用场景。

4. 模板渲染

Django的模板引擎允许将动态数据注入到HTML模板中,并将其呈现给用户。首先 我们需要在的 bbs 目录里创建一个 templates 目录。根据约定优于配置的原则,Django 将会在这个目录里查找模板文件。为啥?还记得我们经常提到 settings.py文件吗?默认的设置文件设置了 DjangoTemplates 后端,并将 APP_DIRS 设置成了 True。这一选项将会让 DjangoTemplates 在每个 INSTALLED_APPS 文件夹中寻找 "templates" 子目录。

python 复制代码
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

在刚刚创建好的templates目录下,再创建一个post文件夹,用于存放我们的模板文件。

html 复制代码
<html>
<head>
    <title>内容列表</title>
</head>

<body>
    {% for post in posts %}
    <h2>{{ post.title }}</h2>
    <div>
        {{ post.content }}
    </div>
    {% endfor %}
</body>
</html>

views.py中我们的视图函数可以这么写,将我们查询得到的post对象传递给 post/index.html

python 复制代码
from django.shortcuts import render, get_object_or_404
from django.http import  HttpResponse, Http404
from bbs.models import Post

def get_posts(request):
    posts = Post.objects.all
    return render(request, 'post/index.html', { 'posts': posts })

通过模板渲染出的页面如图所示:

5.基于类的视图

Django 提供了适用于很多应用的基本视图类。所有视图继承自 View 类,它处理视图链接到 URLs,HTTP 方法调度和其他简单功能。RedirectView 用于 HTTP 重定向,TemplateView 扩展基类来使它能渲染模板。

python 复制代码
urlpattern = [
	path("bbs/about/", TemplateView.as_view(template_name="about.html")),
]

任何传递到 as_view() 的参数将覆盖在类上设置的属性。在这个例子中,我们在 TemplateView 上设置 template_name,用于渲染about.html模板。当然,我们也可以采用继承已存在的视图并覆盖子类里的属性,来提供新的值或方法。

6.404异常处理

对于404异常,我们可以通过以下代码来进行处理:

python 复制代码
def get_post_if_404(request, title):
    try:
        post = Post.objects.get(title = title)
    except Post.DoesNotExist:
        raise Http404("Post Not Exist")
    return render(request, 'post/detail.html', {'post': post})

Django提供了更方便的函数来帮助我们处理此类异常:

python 复制代码
# 便捷写法
def get_post_404(request, title):
    post = get_object_or_404(Post, title=title)
    return render(request , 'post/detail.html', {'post': post})

为什么我们使用辅助函数 get_object_or_404() 而不是自己捕获 ObjectDoesNotExist 异常呢?为什么模型 API 不直接抛出 ObjectDoesNotExist 而是抛出 Http404 呢?

因为这样做会增加模型层和视图层的耦合性。指导 Django 设计的最重要的思想之一就是要保证松散耦合。

7.视图测试

测试是软件开发中十分重要的一个过程,虽然测试并不能使得我们的程序性能更优秀或者更加完美。但是对于中大型软件来说,编写测试用例来进行自动化测试是十分重要的,如果不通过用例来执行测试,意味着我们讲花费大量的时间来验证程序的功能。

按照惯例,Django 应用的测试应该写在应用的 tests.py 文件里。测试系统会自动的在所有以 tests 开头的文件里寻找并执行测试代码。 对于视图测试,Django 提供了一个供测试使用的 Client 来模拟用户和视图层代码的交互。

python 复制代码
def save_post(title, content, pub_date):
    return Post.objects.create(title= title, content = content, pub_date = pub_date)

# Create your tests here.
from django.test import TestCase
from django.utils import timezone
from django.urls import reverse
import datetime
from bbs.models import Post


def save_post(title, content, pub_date):
    return Post.objects.create(title= title, content = content, pub_date = pub_date)

# Create your tests here.
class PostModelTests(TestCase): 
    def test_post_insert_with_future_pub_date(self):

        pub_date = timezone.now() + datetime.timedelta(days=-20)
        # future_post = Post(title = '测试Post', content='测试内容', pub_date=pub_date)
        # self.assertIs(future_post.pub_date_valid(), True)
        future_post = save_post(title = '测试Post', content='测试内容', pub_date=pub_date)
        # 测试路由是否可被访问
        url = reverse("post_detail", args=(future_post.title,))
        response = self.client.get(url)
        self.assertEqual(response.status_code, 200)

通过在命令行运行: python manage.py test bbs 来执行我们的测试用例。

8.总结

Django 视图是 Django 框架中非常重要的一个组成部分,它负责接收用户请求并返回相应的响应。在 Django 中,视图可以分为类视图和函数视图两种。类视图继承自 Django 的 View 类,并提供了一些常用的方法来处理请求和响应。函数视图则是一种简单的方式,它直接接收一个请求并返回一个响应。

除了类视图,Django 还提供了一些其他的视图类型,例如 TemplateView。TemplateView 可以渲染一个模板并将其作为响应返回。为了方便大家学习,我在Github上新建了一个仓库,用于存储文章中涉及的源代码,供大家参考。

总之,Django 视图是 Django 框架中非常重要的一部分,它提供了许多有用的方法来处理请求和响应,并且可以轻松地与 URL 映射和模板引擎等其他功能集成

相关推荐
Estar.Lee6 分钟前
查手机号归属地免费API接口教程
android·网络·后端·网络协议·tcp/ip·oneapi
2401_857610032 小时前
SpringBoot社团管理:安全与维护
spring boot·后端·安全
哭泣的眼泪4082 小时前
解析粗糙度仪在工业制造及材料科学和建筑工程领域的重要性
python·算法·django·virtualenv·pygame
凌冰_2 小时前
IDEA2023 SpringBoot整合MyBatis(三)
spring boot·后端·mybatis
码农飞飞2 小时前
深入理解Rust的模式匹配
开发语言·后端·rust·模式匹配·解构·结构体和枚举
一个小坑货2 小时前
Rust 的简介
开发语言·后端·rust
monkey_meng3 小时前
【遵守孤儿规则的External trait pattern】
开发语言·后端·rust
Estar.Lee3 小时前
时间操作[计算时间差]免费API接口教程
android·网络·后端·网络协议·tcp/ip
新知图书4 小时前
Rust编程与项目实战-模块std::thread(之一)
开发语言·后端·rust
盛夏绽放4 小时前
Node.js 和 Socket.IO 实现实时通信
前端·后端·websocket·node.js