Django是一个非常流行的Python Web框架,它允许开发者轻松构建强大的Web应用程序。上一篇文章中,我们介绍了Python的模型,以及模型相关的使用方法。在本文中,我将详细介绍Django视图的概念和用法,并通过一些示例代码来增强我们对Djang视图的理解。
视图是 Django 中处理 HTTP 请求和生成 HTTP 响应的函数或方法。它们负责处理用户的请求,并返回相应的内容。要创建视图,你需要定义一个函数或方法,并将其绑定到URL。
1.定义视图
首先,在Django项目的根目录下创建一个名为views.py
的文件。在这个文件中,我们将定义我们的视图。
# 在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。
from django.urls import path
from . import views
urlpatterns = [
path('hello/', views.hello, name='hello'),
path('post//', views.title, name='get_post'),
]
在上面的代码中,我们使用 path
函数将URL映射到相应的视图函数。第一个URL模式将 hello/
映射到 hello
视图函数。第二个URL模式将 post/
后面的 title
部分传递给 get_post
视图函数。
3. 视图装饰器
Django提供了一些常用的视图装饰器,可以用于添加额外的功能或进行授权验证。
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" 子目录。
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
文件夹,用于存放我们的模板文件。
内容列表
{% for post in posts %}
{{ post.title }}
{{ post.content }}
{% endfor %}
在views.py
中我们的视图函数可以这么写,将我们查询得到的post
对象传递给 post/index.html
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
扩展基类来使它能渲染模板。
urlpattern = [
path("bbs/about/", TemplateView.as_view(template_name="about.html")),
]
任何传递到 as_view() 的参数将覆盖在类上设置的属性。在这个例子中,我们在 TemplateView 上设置 template_name,用于渲染about.html模板。当然,我们也可以采用继承已存在的视图并覆盖子类里的属性,来提供新的值或方法。
6.404异常处理
对于404异常,我们可以通过以下代码来进行处理:
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提供了更方便的函数来帮助我们处理此类异常:
# 便捷写法
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 来模拟用户和视图层代码的交互。
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 映射和模板引擎等其他功能集成