6.2 视图的高级特性和快捷方法
2025-02-17
6.2.1 URL的反向解析
在处理业务需求的过程中可能会需要视图的URL模式,如返回重定向或在模板中用于链接到其他的视图。但是,由于URL可能随着业务调整发生变化,因此将URL硬编码到代码中并不友好。Django为了解决这个问题,提供了URL反向解析的方法,通过给URL模式命名即可反向解析得到完整的URL
reverse方法
- path方法:传递两个参数:URL模式和模式,path还支持接受一个
name,用于指定当前URL模式的名字 - URL的反向解析就可以利用这个指定的
name去完成
# post/urls.py
urlpatterns = [
path('dymmmic/<int:year>/<mth:month>/<int:day>/', views.dynamic_hello, name='dynamic_hello'),
]- 利用reverse实现反向解析的定义
- viewname:它可以是
URL模式的名字,即name所指定的名称;也可以是可调用的视图对象,例如dynamic_hello视图 - urlconf:这个属性用于决定当前的反向解析使用哪个
URLconf模块,默认是根URLconf - args:它用于传递参数,可以是元组或者列表,顺序填充URL中的位置参数
- kwargs:它与args一样,也用于传递参数;但它是字典类型的,使用关键字指定参数和数值。需要注意,args与kwargs不可以同时出现
- current_app:它指示当前执行的视图所属的应用程序
- viewname:它可以是
reverse(viewname, urlconf=None, args=None, kwargs=None, current_app=None)# post/views.py
from django.urls import reverse
def dynamic_hello_reverse(request):
return HttpResponseRedirect(reverse('dynamic_hello',args=(2018,9,16)))命名空间
- URL命名空间使得即使在不同的应用中定义了相同的URL名称,也能够反向解析到正确的URL
- URL命名空间分为两部分:
- 应用命名空间(app_name):是正在部署的应用名称,应用的每一个实例都有相同的命令空间,可以通过app_name和name(URL名称)区分不同应用的URL,之间使用
:连接 - 实例命名空间(namespace):用来标识一个应用的特定实例,主要功能:区分同一个应用部署的多个不同实例
- 应用命名空间(app_name):是正在部署的应用名称,应用的每一个实例都有相同的命令空间,可以通过app_name和name(URL名称)区分不同应用的URL,之间使用
以例子举例,能容易理解
- 项目的urls.py文件中给post应用添加namespace
# urls.py
path('post/', incluse('post.urls', namespace='bbs_post'))- 在post应用的urls.py中给出app_name的声明
# post/urls.py
app_name= 'post'- 最后,修改dynamic_hello_reverse视图的定义
# post/views.py
def dynamic_hello_reverse(request):
return HttpResponseRedirect(reverse('post:dynamic_hello',args=(2022,9,28),current_app=request.resolver_match.namespace))
# HttpResponseRedirect 视图重定向
6.2.2 视图重定向
- 使用HttpResponseRedirect进行视图重定向
- 快捷方法:
redirect()(django/shortcuts.py)- 除了传递URL,可以接受对象和视图完成重定向
1. 永久重定向和临时重定向
- 302:临时重定向(HttpResponseRedirect响应的状态码是临时重定向),常用于:同一站点内的跳转,(如未登录用户访问页面重定向到登录页)
- 301:永久重定向,指被请求的资源已经永久移动到新的位置,将来任何对此资源的引用都应该使用本相应返回的若干URL之一,常用于:域名跳转
2. redirect()方法
- 定义
redirect(to, *args, permanent=False, **kwargs)*args,**kwargs最终会传递到reverse方法中,是用来标注URL的参数permanent=False:实现302跳转,True:实现301跳转
- 必填参数:
to,接受三种类型的参数
带有get_absolute_url属性(方法)的对象
def hello_redirect(request):
class A:
@classmethod
def get_absolute_url(cls):
return '/post/topic_list'
return redirect(A)此时访问:hello_redirect视图会跳转到topci_list视图(话题列表页)常见的用法:Model中定义get_absolute_url()方法,传递Model实例对象到redirect中,跳转到Model实例的详情信息页
例子:给Topic对象添加get_absolute_url()方法
class Topic(BaseModel): def get_absolute_url(self): return '/post/topic/%s' % self.id
传递URL模式的名称
- 即path中配置的name值(如果配置了命名空间,也需要指定)
- 内部实现是通过reverse方法反向解析得到URL
def hello_redirect(request):
return redirect('post:dynamic_hello',2022,9,28)传递绝对或相对URL
- 直接指定跳转的位置
- 例子:直接指定重定向到话题列表页
def hello_redirect(request):
return redirect('/post/topic_list/')- 相对URL使用
./或../,与文件系统路径类似
def hello_redirect(request):
return redirect('./xxx/')
# 当前的视图URL是 /post/hello_redirect/ 访问此连接会跳转到/post/hello_redirect/xxx/
def hello_redirect2(request):
return redirect('../topic_list/')
# 当前的视图URL是 /post/hello_redirect2/ 访问此连接会跳转到/post/topic_list/6.2.3 常用的快捷方法
render
将给定的模块和上下文字典组合,渲染返回一个HttpResponse对象
定义
render(request, template_name, context=None, content_type=None, status=None, using=None)
必须参数:
- request:HttpReponse对象,视图函数的第一个参数
- template_name:字符串或字符串列表
- 字符串:表示模板的完整路径
- 列表:按照顺序找到第一个存在的模板
可选参数:
- context:默认是一个空字典,通过传递它渲染模板
- content_type:生成文档的MIME类型。默认为
DEFAULT_CONTENT_TYPE设定的值 - status:相应状态码。默认200
- using:指定加载模板的模板引擎
例子
from django.shortcuts import render
def topic_list_view(request):
"""
话题列表
:param request:
:return:
"""
topic_qs = Topic.objects.all()
result = {
'count': topic_qs.count(),
'info': [build_topic_base_info(topic) for topic in topic_qs]
}
return render(request, 'post/topic_list.html', result)render_to_response
- 功能与render一样,根据一个给定的上下文字典渲染模板并返回HttpResponse
- 定义
render_to_response(template_name, context=None, content_type=None, status=None, using=None)
- 没有传递request,在模板中的使用会受到一定的限制
- 如不能直接通过request对象获取它的相关属性
此方法可能被弃用,应该优先考虑render方法
get_object_or_404
- 通过Model对象的get方法获取实例对象,当实例不存在的时候,自动捕捉DoesNotExist异常,并返回404响应
- 定义
get_object_or_404(klass, *args, **kwargs)
*args, **kwargs:是查询对象时用到的查询参数,应该是get和filter可以接受的格式klass:可以使Model对象,Manager或QuerySet实例
get_object_or_404不会抛出DoesNotExist异常,但是如果传递的条件匹配了多个实例对象,则仍然会抛出MultipleObjectsReturned异常
- 例子
from django.shortcuts import get_object_or_404
# 传递 Topic
get_object_or_404(Topic, pk=1)
# 这个方法在正常执行时返回的是Model实例对象,并不是HttpResponse
# 传递 Manager实例
get_object_or_404(Topci.objects, pk=1)
# 传递 QuerySet实例
topic_qs = Topic.object.filter(id__gte=1)
get_object_or_404(topic_qs, pk=1)get_list_or_404
- 用来获取Model实例对象的列表,当获取的结果为空,返回404响应
- 定义
get_list_or_404(klass, *args, **kwargs)
- 匹配的时候,使用的是filter方法而不是get方法
- 例子
from post.models import Topic
from django.shortcuts import get_list_or_404
get_list_or_404(Topic)get_object_or_404 和 get_list_or_404 常用于不考虑“兼容”的场景中,即匹配不到实例对象就返回找不到资源(404)。这两个方法会比自己去查询校验并返回404响应要简单很多,所以,如果需要这样的场景,就首先考虑使用它们