django -- 视图
视图
视图就是一个python函数或者类,它接受web请求并返回web响应,响应可以是一个字符串或者HTML文件,也可以是一个重定向。无论视图写在哪里,都要返回响应,所以代码写在哪里都无所谓,但是为了规范,大家通常把视图放在项目或者app目录中的views.py文件中
先来看一个简单的视图
from django.shortcuts import render def index(request): return render(request,"index.html")
代码解释:
- 首先,我们从django.shortcuts里面导入了render类
- 接着,我们定义了index函数,它就是视图函数,每个视图函数都使用request对象作为第一个参数
- 最后,这个视图函数会返回一个index.html的文件
CBV
我们之前写的图书管理系统,都是基于函数的view,叫做FBV(function based view),还可以把view写成基于类的,叫做CBV(class based view)
FBV版
def add_press(request): if request.method == 'POST': name = request.POST.get('name') Press.objects.create(name=name) return redirect('/press_list/') return render(request,'add_press2.html')
CBV版
from django.views import View # 导入View类 class AddPress(View): # 要继承View类 def get(self, request): return render(request, 'add_press2.html') def post(self, request): name = request.POST.get('name') Press.objects.create(name=name) return redirect('/press_list/')
注意:
使用CBV时,urls.py中也做对应的修改:
url(r'^add_press/', views.AddPress.as_view()),
函数名是固定的,如果是get请求则会执行get方法,如果是post请求,则会执行post方法
CBV的流程:
- 定义CBV,要继承View类
- 修改对应的路由
- AddPress.as_view()在请求没来之前执行这句,执行完的结果是view(可以去看源码)
- 当请求到来的时候执行view函数,执行了如下的步骤
1. 实例化自己写的类 —— 》self
self = cls(**initkwargs)
2. self.request = request
3. 执行 self.dispatch(request, *args, **kwargs)
1. 执行父类中的dispatch方法
1. 判断请求方式是否被允许
1. 允许的情况
handler = 通过反射获取 get post 方法
2. 不允许的情况
handler = 不允许的方法
3. handler(request, *args, **kwargs)
2. 返回HttpResponse对象
4. 返回HttpResponse对象 给django
CBV使用装饰器
给CBV使用装饰器有三种方法,我们先来写个装饰器,统计一下请求执行所需要的时间
def wrapper(func): def inner(*args, **kwargs): start_time = time.time() ret = func(*args, **kwargs) end_time = time.time() print("执行时间为:", end_time-start_time) return ret return inner
如果是给函数使用装饰器,我们直接在函数上面写@wrapper就可以了
第一种方法,给类里的方法加装饰器,如果要给CBV加装饰器,首先要导入django提供的一个类,才能使用
from django.utils.decorators import method_decorator
想给哪个方法使用装饰器,就直接在该方法上面写
@method_decorator(装饰器名)
给get方法加装饰器
from django.utils.decorators import method_decorator class AddPress(View): # 要继承view类 @method_decorator(wrapper) def get(self, request): print('get') return render(request, 'add_press2.html') def post(self, request): print('post') name = request.POST.get('name') Press.objects.create(name=name) return redirect('/press_list/')
第二种方法:给类加装饰器
@method_decorator(wrapper, name='get') @method_decorator(wrapper, name='post') class AddPress(View): # 要继承view类 def get(self, request): print('get') return render(request, 'add_press2.html') def post(self, request): print('post') name = request.POST.get('name') Press.objects.create(name=name) return redirect('/press_list/')
给类加装饰器必须要有一个name,值为要装饰的方法名。因为要给两个方法都加,所以要写两个
第三种方法:
请求过来后会先执行dispatch()这个方法,如果需要批量对具体的请求处理方法,如get,post等做一些操作的时候,这里我们可以手动改写dispatch方法,这个dispatch方法就和在FBV上加装饰器的效果一样。
from django.utils.decorators import method_decorator class AddPress(View): # 要继承view类 @method_decorator(wrapper) def dispatch(self, request, *args, **kwargs): # 重写dispatch方法 ret = super().dispatch(request, *args, **kwargs) return ret def get(self, request): print('get') return render(request, 'add_press2.html') def post(self, request): print('post') name = request.POST.get('name') Press.objects.create(name=name) return redirect('/press_list/')
使用第三种方法,我们就给类下面的所有方法都加上了装饰器
Request对象
当一个页面被请求时,Django就会创建一个包含本次请求原信息的HttpRequest对象。
Django会将这个对象自动传递给相应的视图函数,一般视图函数约定俗成地使用 request 参数承接这个对象。
属性
- request.path_info 返回用户访问url,不包括域名
- request.method 请求中使用的HTTP方法的字符串表示,全大写表示。
- request.GET 包含所有HTTP GET参数的类字典对象
- request.POST 包含所有HTTP POST参数的类字典对象
- request.body 请求体,byte类型 request.POST的数据就是从body里面提取到的
- request.scheme 表示请求方案的字符串(通常为http或https)
- request.body 一个字符串,代表请求报文的主体。在处理非 HTTP 形式的报文时非常有用,例如:二进制图片、XML,Json等。但是,如果要处理表单数据的时候,推荐还是使用 HttpRequest.POST
- request.path 一个字符串,表示请求的路径组件(不含域名)
- request.encoding 一个字符串,表示提交的数据的编码方式(如果为 None 则表示使用 DEFAULT_CHARSET 的设置,默认为 'utf-8')。
- request.COOKIES 一个标准的Python 字典,包含所有的cookie。键和值都为字符串
- request.FILES 一个类似于字典的对象,包含所有的上传文件信息。FILES 中的每个键为<input type="file" name="" /> 中的name,值则为对应的数据。注意,FILES 只有在请求的方法为POST 且提交的<form> 带有enctype="multipart/form-data" 的情况下才会包含数据。否则,FILES 将为一个空的类似于字典的对象
- request.META 一个标准的Python 字典,包含所有的HTTP 首部。具体的头部信息取决于客户端和服务器,
request.META.get('REMOTE_ADDR')获取客户端的IP
- request.user 一个 AUTH_USER_MODEL 类型的对象,表示当前登录的用户。如果用户当前没有登录,user 将设置为 django.contrib.auth.models.AnonymousUser 的一个实例。你可以通过 is_authenticated() 区分它们
- request.session 一个既可读又可写的类似于字典的对象,表示当前的会话。只有当Django 启用会话的支持时才可用
方法
- request.get_host() 返回IP地址和端口
- request.get_full_path() 返回 path,可以将加上查询字符串。
- request.is_secure() 如果请求时是安全的,则返回True;即请求通是过 HTTPS 发起的
- request.is_ajax() 如果上ajax发送的,则为True
Response对象
与由Django自动创建的HttpRequest对象相比,HttpResponse对象是我们的职责范围了。我们写的每个视图都需要实例化,填充和返回一个HttpResponse
属性
- HttpResponse.content:响应内容
- HttpResponse.charset:响应内容的编码
- HttpResponse.status_code:响应的状态码
JsonResponse对象
如果我们使用HttpResponse想返回一个字典,直接返回的话,页面上只能看到字典的key,这时候可以使用json.dumps()转化为字符串返回给页面,而Django提供了我们一个方法,可以直接返回字典,类型是json
首先需要导入
from django.http import JsonResponse
def json_data(request): dic = {'name':'zouzou', 'age':'18'} # return HttpResponse(dic) return JsonResponse(dic)
这时候返回的Content-Type:application/json
默认只能传递字典类型,如果要传递非字典类型需要设置一下safe关键字参数。
response = JsonResponse([1, 2, 3], safe=False)