1. 视图 View
视图 View |
- 一个视图函数(类),简称视图,是一个简单的Python函数(类),它接受web请求并且返回web响应。
- 响应可以是一个网页的html内容,一个重定向,一个404错误,一个xml文档,或者一张图片。
- Django使用请求和响应对象来通过系统传递状态。每个视图函数都使用HttpRequest对象作为第一个参数,并且通常称之为request。
- 当浏览器向服务器请求一个页面时,Django创建一个HttpRequest对象,该对象包含关于请求的元数据。然后,Django加载相应的视图,将这个HttpRequest对象作为第一个参数传递给视图函数,每个视图负责返回一个HttpResponse对象
- 在MVC模式中,视图代表的是html页面的内容;在MTV模式中,视图是用来处理业务逻辑的
1.1 FBV和CBV
FBV和CBV |
def xxx(request):
#处理业务逻辑
return response
#url.py
url(r'xxx/,xxx')
def publisher_add(request):
if request.method == 'POST':
pub_name = request.POST.get('pub_name')
if not pub_name:
error = '输入不能为空'
return render(request,'publisher_add.html',{'error':error})
if models.Publisher.objects.filter(name=pub_name):
error = '出版社名称已存在'
return render(request,'publisher_add.html',{'error':error})
ret = models.Publisher.objects.create(name=pub_name)
return redirect('/app01/publisher_list/')
return render(request,'publisher_add.html')
CBV Class Based View
from django.views import View
class PublisherAdd(View):
def get(self,reqest):
#处理get请求
使用self.request获取请求信息和request一样,因为在执行as_view的view方法时,对request对象进行了封装
return response
def post(self,reqest):
#处理post请求
return response
#url.py
url(r'publisher_add/',PublisherAdd.as_view())
class PublisherAdd(View):
def get(self,request):
return render(request,'publisher_add.html')
def post(self,request):
pub_name = request.POST.get('pub_name')
error = ''
if not pub_name:
error = '输入不能为空'
return render(request,'publisher_add.html',{'error':error})
if models.Publisher.objects.filter(name=pub_name):
error = '出版社名称已存在'
return render(request,'publisher_add.html',{'error':error})
else:
models.Publisher.objects.create(name=pub_name)
return redirect('/app01/publisher_list/')
- Django中的类视图拥有自动查找制定方法的功能,通过调用as_view()方法实现。
- 设计思想:把视图函数的逻辑定义到类的方法里,然后在函数中实例化这个类,通过调用类的方法实现函数逻辑。而把逻辑定义到类中的一个好处就是可以通过继承复用这些方法。
- as_view(类方法)的执行流程:
- 程序加载时,执行PublisherAdd.as_view(),as_view返回值是view函数名,即返回一个view函数(as_view内的view函数)
- 程序执行时,执行view函数
- 实例化所调用的类,即PublisherAdd,并将PublisherAdd实例化对象赋值给self;
- self.request = request ,封装request对象
- 对象执行self.dispatch方法
- 判断请求是否被允许
- 允许
- 通过反射获取请求方式对应请求方法,将结果返回给handler;
- 获取不到self.http_method_not_allowed方法返回值赋值给handler;
- 不允许
- self.http_method_not_allowed方法返回值赋值给handler;
- 允许
- 执行handler 将方法的结果返回
- 判断请求是否被允许
- 调用顺序:as_view–>view–>dispatch
- 可以看出as_view实际上是一个闭包,作用就是做一些检验工作,再返回view方法
- view方法的作用是给请求对象补充三个参数(self.request, self.args, self.kwargs),并调用dispatch方法处理
- dispatch方法查找到指定的请求方法,并执行相应代码块
1.2 给视图加装饰器
给视图加装饰器 |
- FBV
- 直接加,FBV本身就是一个函数,所以和普通的函数加装饰器无差别
- CBV
from django.utils.decorators import method_decorator
1.加在方法上 @method_decorator(timer) def get(self,request): return render(request,'publisher_add.html') 2.加在dispatch方法上(在PublisherAdd类中重写dispatch方法) @method_decorator(timer) def dispatch(self,request,*args,**kwargs): ret = super().dispatch(self,request,*args,**kwargs) # 执行View中的dispatch方法 return ret @method_decorator(timer,name='dispatch') class PublisherAdd(View): 3.加在类上 @method_decorator(timer,name='get') @method_decorator(timer,name='post') class PublisherAdd(View):
1.3 Request对象
Request对象 |
- 当页面被请求时,Django就会创建一个包含本次请求原信息的HttpRequest对象
- Django会将这个对象自动传递给响应的视图函数,一般视图函数约定俗成地使用request参数承接这个对象
属性:
- request.method 一个字符串,表示请求中使用的HTTP方法,全大写表示
- 请求方式 GET POST
- request.GET 包含所有HTTP GET参数的类字典对象
- url上携带的参数 ?k1=v1&k2=v2 以字典形式传递给后台{ } request.GET[‘k1’] /request.GET.get(‘k1’)
- request.POST 包含所有HTTP GET参数的类字典对象
- POST请求提交的数据,如果请求中包含表单数据,则将这些数据封装成QueryDict对象
- 以字典形式传递给后台{ } 编码格式是urlencode
- POST 请求可以带有空的 POST 字典 —— 如果通过 HTTP POST 方法发送一个表单,但是表单中没有任何的数据,QueryDict 对象依然会被创建。因此,不应该使用 if request.POST 来检查使用的是否是POST 方法;应该使用 if request.method == “POST”
- request.body 一个字符串,代表请求报文的主体。
- 请求体,byte类型 request.POST的数据就是从body里面取到的
- request.FILES 一个类似于字典的对象,包含所有的上传文件信息
- FILES中的每个键为<input type=“file” name="" / >中的name,值则为对应的数据
- FILES只有在POST请求时,且提交的标签带有enctype=“multipart/form-data” 的情况下才会包含数据,否则,FILES将为一个空的类似于字典的对象
上传文件示例: .html <form action="" method="post" enctype="multipart/form-data" > <input type="file" name="index"> <button>上传</button> </form> #view.py f1=request.FILES.get('ffff') f1.name #获取上传文件的名字 for i in f1: f.write(i) def upload(request): if request.method == "POST": # 从请求的FILES中获取上传文件的文件名,index为页面上type=files类型input的name属性值 filename = request.FILES["index"].name # 在项目目录下新建一个文件 with open(filename, "wb") as f: # 从上传的文件对象中一点一点读 for chunk in request.FILES["index"].chunks(): # 写入本地文件 f.write(chunk) return HttpResponse("上传OK")
- request.META 一个标准的python字典,包含所有HTTP头部信息
- 请求中的任何 HTTP 头部转换为 META 的键时,都会将所有字母大写并将连接符(-)替换为下划线(_),最后加上 HTTP_ 前缀。
- Accept-Language 转换成META 的键为 HTTP_ACCEPT_ENCODING
- request.path_info 返回用户访问的url,不包括域名
- rrequest.COOKIES cookie的信息
- request.session session的信息
方法:
- request.get_full_path() 完整的路径,不包含IP和端口号,包含参数 ?k1=v1&k2=v2
- request.is_ajax() 是否是ajax请求,如果请求是通过XMLHttpRequest 发起的,则返回True
1.4 Response对象
Response对象 |
Django服务器接收到客户端发送过来的请求后,会将提交上来的这些数据封装成一个 HttpRequest 对象传给视图函数。那么视图函数在处理完相关的逻辑后,也需要返回一个响应给浏览器。而这个响应,我们必须返回 HttpResponseBase 或者他的子类的对象。而 HttpResponse 则是 HttpResponseBase 用得最多的子类。
HttpResponse
- HttpResponse(”字符串") 返回字符串
- HttpResponse.content:响应内容
- HttpResponse.charset:响应内容的编码
- HttpResponse.status_code:响应的状态码
render
- 结合一个给定的模板和一个给定的上下文字典,并返回一个渲染后的HttpResponse对象
- render(request,“模板的文件名”,{ })
def render(request, template_name, context=None, content_type=None, status=None, using=None):
"""
Returns a HttpResponse whose content is filled with the result of calling
django.template.loader.render_to_string() with the passed arguments.
"""
content = loader.render_to_string(template_name, context, request, using=using)
return HttpResponse(content, content_type, status)
- request:用于生成响应的对象
- template_name:要使用的模板的完整名称,可选参数
- context:添加到模板上下文的一个字典,默认是一个空字典。如果字典中的值是可调用的,视图将在渲染模板前调用它
- content_type:生成的文档要使用的MIME类型,默认为"text/html"
- status:响应的状态码,默认为200
- using:用于加载模板的模板引擎的名称
redirect
- redirect(“地址”) 重定向 Location:“地址” 状态码301(永久重定向) 302(临时重定向)
- 默认情况下,redirect()返回一个临时重定向,一下三种形式都接收一个permanent参数;如果设置为True,将返回一个永久重定向。
- 参数可以是:
- 一个模型(一个具体的ORM对象):将调用模型的get_absolute_url() 函数
- 一个视图,可以带有参数:将使用urlresolvers.reverse 来反向解析名称
- 一个绝对的或相对的URL,将原封不动的作为重定向的位置。
from django.shortcuts import redirect
1.传递一个具体的ORM对象(模型):
def my_view(request):
...
object = MyModel.objects.get(...)
return redirect(object)
2.传递一个视图的名称
def my_view(request):
...
return redirect('some-view-name', foo='bar')
3.传递要重定向到的一个具体的网址
def my_view(request):
...
return redirect('/some/url/')
# return redirect('http://example.com/') 也可以是一个完整的网址
JsonResponse
- JsonResponse({ }) Content-Type = application/json JsonResponse([ ],safe=False)
- JsonResponse是HttpResponse的子类,专门用来生成JSON编码的响应,且Content-Type = application/json
from django.http import JsonResponse
def index(request):
# response = JsonResponse({'name': 'alex','age':18})
# print(response.content)
return JsonResponse({'name': 'alex','age':18})
- 默认只能传递字典类型,如果要传递非字典类型需要设置一下safe关键字参数。
from django.http import JsonResponse
def index(request):
persons = ["张三","李四","王五"]
return JsonResponse(persons,safe=False)