Django视图函数技巧,从入门到实战

文章目录

Django视图函数

Django中一个视图函数(类),简称视图,是一个简单的Python 函数(类),它接受Web请求并且返回Web响应。

响应可以是一张网页的HTML内容,一个重定向,一个404错误,一个XML文档,或者一张图片。

无论视图本身包含什么逻辑,都要返回响应。大家约定成俗将视图放置在项目(project)或应用程序(app)目录中的名为views.py的文件中。

视图读取参数

url以查询字符串的方式传参,使用request.GET.get("name", default)的形式获取参数值

url以路径传参,使用路径转换器来进行获取参数,在django1.0版本的时候只能通过正则表达式来获取参数。

1.request对象的方法

request.GET:获取url中的查询字符串的数据

request.POST: 获取表单提交的数据

request.path:获取请求的路径

request.method:获取请求的方法得到的值是 请求方法GET or POST等 大写

request.COOKIES:获取请求过来的cookies

request.user:获取请求的用户对象,可以通过它判断用户是否登录,并获取用户信息

request.session:一个既可读又可写的类似字典的对象,表示当前会话

request.META:一个标准的Python字典,包含所有的HTTP首部。具体的头部信息取决于客户端和服务器,

#request.META 字典类型数据,所有的请求头的键都加上了一个HTTP_键名称

print(request.get_full_path()) #当前请求路径包含查询参数

request.encoding

一个字符串,表示提交的数据的编码方式(如果为 None 则表示使用 DEFAULT_CHARSET 的设置,默认为 'utf-8')。

这个属性是可写的,你可以修改它来修改访问表单数据使用的编码。

接下来对属性的任何访问(例如从 GET 或 POST 中读取数据)将使用新的 encoding 值。

如果你知道表单数据的编码不是 DEFAULT_CHARSET ,则使用它。

request.GET 获取查询参数,#不管是post或get请求,当url中含有查询参数时,要在后台的request对象中获取查询参数

,用的属性都是request.GET

浏览器输入查询参数 a=1&b="景浩"

获取的字典,值是列表类型

print(request) 获取的是WSGIRequest对象

2.视图函数的常用的返回对象

HttpResponse对象,可以直接返回一些字符串

render: 将数据在模板中渲染并显示,使用方式为return render(request, template_path, {k:v})字典中key与value就是要向前端渲染出的数据。

JsonResponse返回一个json类型,通常用于与前端进行ajax交互

(1)response对象

属性

HttpResponse.content:响应内容

HttpResponse.charset:响应内容的编码

HttpResponse.status_code:响应的状态码

(2)JsonResponse对象

JsonResponse是HttpResponse的子类,专门用来生成JSON编码的响应。

class JsonResponse(data, encoder=DjangoJSONEncoder, safe=True, json_dumps_params=None,**kwargs)

这个类是HttpRespon的子类,它主要和父类的区别在于:

1.它的默认Content-Type 被设置为: application/json

2.第一个参数,data应该是一个字典类型,当 safe 这个参数被设置为:False ,那data可以填入任何能被转换为JSON格式的对象,比如list, tuple, set。 默认的safe 参数是 True. 如果你传入的data数据类型不是字典类型,那么它就会抛出 TypeError的异常。

3.json_dumps_params参数是一个字典,它将调用json.dumps()方法并将字典中的参数传入给该方法。

使用HttpResponse对象来响应数据的时候,还可以通过content_type指定格式:

return HttpResponse(json.dumps(data),content_type="application/json")

默认只能传递字典类型,如果要传递非字典类型需要设置一下safe关键字参数。

response = JsonResponse([1, 2, 3], safe=False)

(3)redirect() :给浏览器了一个30x的状态码

参数可以是:

  1. 一个模型:将调用模型的get_absolute_url() 函数

2.一个视图,可以带有参数:将使用urlresolvers.reverse 来反向解析名称

3.一个绝对的或相对的URL,将原封不动的作为重定向的位置。

默认返回一个临时的重定向;传递permanent=True 可以返回一个永久的重定向。

示例:

你可以用多种方式使用redirect() 函数。

传递一个具体的ORM对象(了解即可)

将调用具体ORM对象的get_absolute_url() 方法来获取重定向的URL:

301 redirect: 301 代表永久性重定向 网址永久地迁移了,原网址下的资源都没有了

302 redirect: 302 代表临时重定向 临时的做个跳转,项目可能在升级,原网址资源还在

重定向案例

首先在url里面新添加一个用来重定向的路径

建个新页面

视图函数里面,添加跳转视图函数new(),并在login2路径下,用户输入用户名jinghao 即重定向到 /new/ 新页面

redirect里面写的第一个参数为路径,可以添加第二个参数permanent=True,表示永久重定向。默认是临时重定向

浏览器访问,输入用户名jinghao,实现跳转

永久重定向

3.设置响应头和状态码

理论上,客户端发来请求,服务端应根据响应的成功与否,发送给客户端相关的状态码

服务器报错,也应该返回状态码告诉客户端是什么错误

响应对象主要有三种形式:

HttpResponse() 回复字符串 默认响应状态码是200

render() 回复页面内容 默认响应状态码是200

redirect() 重定向 默认响应状态码是302


如果发生什么问题,比如经过各种逻辑判断逻辑有误,参数不对等,服务端此时应该回复异常的状态码

(1)设置响应头键值对

def code(request):

ret = HttpResponse("状态码")

ret['name'] = "jinghao" # 添加响应头键值对 #会调用HttpResponse setattr方法,在setattr()方法中对响应头键值对进行了封装

return ret

浏览器访问查看

响应数据在前端都能拿到,拿出来就可以做一些处理

比如用户名密码认证成功之后,比如加个键值对 isLogin=True

响应头在客户端拿到以后,再登录某个页面之后,可以携带这个数据,后台拿到这个数据之后,就知道该用户已经登录了,不用重新登录

(2)设置响应状态码

#设置状态码

def code(request):

ret = HttpResponse("状态码")

ret['name'] = "jinghao" # 添加响应头键值对 #HttpResponse setattr

ret.status_code = 404 # 修改状态码

return ret

正常状态下不需要设置状态码,但为了接口规范,一些情况下需要设置状态码

render HttpResponse Redirect 三种响应方式都可以修改响应状态码

4.CBV模式

FBV(function base views) 就是在视图里使用函数处理请求。

之前都是FBV模式写的代码,所以就不写例子了。

CBV(class base views) 就是在视图里使用类处理请求。

Python是一个面向对象的编程语言,如果只用函数来开发,有很多面向对象的优点就错失了(继承、封装、多态)。

所以Django在后来加入了Class-Based-View。可以让我们用类写View。

这样做的优点主要下面两种:

提高了代码的复用性,可以使用面向对象的技术,比如Mixin(多继承)

可以用不同的函数针对不同的HTTP方法处理,而不是通过很多if判断,提高代码可读性

如果用class-based view写的话,就是下面这样

(1)CBV模式写法,先引入类

from django.views import View

#自己写的类要继承View类

class BookView(View):

通过反射获取到请求方法对应的类中的方法来执行

#需要什么类型的请求。就定义什么方法,比如get,post,方法名固定

def get(self,request):

return HttpResponse('book')

需要处理什么请求方法,就写对应名称的方法

根据其继承的类,我们可以看到,原码中支持的八种方法类型,我们在类中写的方法必须是这八种方法其中的一种,不然会报错

Django的url是将一个请求分配给可调用的函数的,而不是一个class。

针对这个问题,class-based view提供了一个as_view()静态方法(也就是类方法),调用这个方法,会创建一个类的实例,

然后通过实例调用dispatch()方法,dispatch()方法会根据request的method的不同调用相应的方法来处理request(如get() , post()等)。

到这里,这些方法和function-based view差不多了,要接收request,得到一个response返回。如果方法没有定义,会抛出HttpResponseNotAllowed异常。

原码部分

python 复制代码
def dispatch(self, request, *args, **kwargs):
    # Try to dispatch to the right method; if a method doesn't exist,
    # defer to the error handler. Also defer to the error handler if the
    # request method isn't on the approved list.
    if request.method.lower() in self.http_method_names: #get
        # ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']
        handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
    else:
        handler = self.http_method_not_allowed
    return handler(request, *args, **kwargs) 就是get  # HttpResponse('ok')

dispatch方法就是为了获取我们在类中写的方法,然后返回方法执行返回结果 

注意:使用CBV时,urls.py中也做对应的修改:

from django.contrib import admin
from django.urls import path
from login import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', views.login),
    # path('login/', views.login),
    # path('logininfo/', views.logininfo),
    path('login2/', views.login2),
    path('new/', views.new),
    path('code/', views.code),
    path('book/', views.BookView.as_view()),  注意,这里是views.类名.as_view()
]

我们继承的类View类中有as_view方法

浏览器访问

(2)CBV模式下传参

创建个文章类

使用get方法

如果想看2018年的文章

urls.py路径需要配置,year是变量名,需要再视图函数里面传进去

views视图函数需要传参year

浏览器访问

article/后面只要是个int类型的数字数字都可以访问

使用post方法提交表单,post方法也要传参

form表单使用post方法,在当前页面提交

浏览器显示

输入一个用户名提交

后端可以通过request.POST获取提交数据。获取的是QueryDict字典类型,字典的值是列表

相关推荐
Yyyyy123jsjs14 分钟前
Python 如何做量化交易?从行情获取开始
开发语言·python
长安牧笛19 分钟前
制作无人直播文案生成工具,输入直播主题,产品信息,自动生成直播文案,支持一键复制
python
廋到被风吹走30 分钟前
【Spring】DefaultListableBeanFactory 详解
java·python·spring
子夜江寒30 分钟前
Python 操作 MySQL 数据库
数据库·python·mysql
梦帮科技37 分钟前
第二十二篇:AI驱动的工作流优化:性能瓶颈自动检测
数据结构·数据库·人工智能·python·开源·极限编程
myzzb41 分钟前
python调用ffmpeg.exe封装装饰类调用
python·学习·ffmpeg·开发
小鸡吃米…42 分钟前
Python - 多重继承
开发语言·python
悟能不能悟42 分钟前
java list怎么进行group
java·python·list
在等星星呐1 小时前
人工智能从0基础到精通
前端·人工智能·python
世界唯一最大变量1 小时前
自创的机械臂新算法,因为是AI写的,暂时,并不智能,但目前支持任何段数
python·排序算法