视图函数view
一个视图函数(类),简称视图,是一个简单的Python 函数(类),它接受Web请求并且返回Web响应。响应可以是一张网页的HTML内容,一个重定向,一个404错误,一个XML文档,或者一张图片。
CBV和FBV
FBV
在视图里使用函数处理请求
from django.shortcuts import render,HttpResponse
# Create your views here.
def login(request):
if request.method == "GET":
return render(request,"login.html")
else:
if request.POST.get("username") == "lai" and request.POST.get("password") == "123":
return render(request,"show.html")
# return HttpResponse('登录成功')
else:
return render(request,"login.html")
# return HttpResponse('失败')
CBV
Python是一个面向对象的编程语言,如果只用函数来开发,有很多面向对象的优点就错失了(继承、封装、多态).Django在后来加入了Class-Based-View。可以使用类类写View。
优点:
- 提高了代码的复用性,可以使用面向对象的技术
- 可以用不同的函数针对不同的HTTP方法处理,而不是通过很多if判断,提高代码可读性
# views.py
from django.views import View
from django.shortcuts import render,HttpResponse
class Login(View): # 继承view
def dispatch(self, request, *args, **kwargs): # 重写父类方法
print("请求前的操作")
ret = super().dispatch(request, *args,**kwargs)
print("请求后的操作")
return ret
def get(self,request): # 处理get请求
return render(request,"index.html")
def post(self,request): # 处理post请求
return HttpResponse("登陆成功")
CBV在url路径配置中和FBV有些不同,CBV需要添加as_view ()
方法
# urls.py
from app1 import views
urlpatterns = [
url(r'^admin/', admin.site.urls), # FBV
url(r'^index/', views.Login.as_view()), # CBV 路径需要使用as_view方法
添加装饰器
FBV添加装饰器
FBV本身就是一个函数,所以和给普通的函数加装饰器无区别:
def wrapper(func):
def inner(*args, **kwargs):
start_time = time.time()
ret = func(*args, **kwargs)
end_time = time.time()
print("used:", end_time-start_time)
return ret
return inner
# FBV版添加班级
@wrapper
def add_class(request):
if request.method == "POST":
class_name = request.POST.get("class_name")
models.Classes.objects.create(name=class_name)
return redirect("/class_list/")
return render(request, "add_class.html")
CBV添加装饰器
类中的方法与独立函数不完全相同,因此不能直接将函数装饰器应用于类中的方法 ,需要先将其转换为方法装饰器。Django中提供了method_decorator装饰器用于将函数装饰器转换为方法装饰器。
from django.views import View
from django.shortcuts import render,HttpResponse
from django.utils.decorators import method_decorator # 导入模块
def a(obj): # 装饰器
def b(*args,**kwargs):
print("装饰器前")
ret = obj(*args,**kwargs)
print("装饰器后")
return ret
return b
# 方式一
@method_decorator(a,name="get") # get请求触发装饰器
@method_decorator(a,name="post") # post请求触发装饰器
class Login(View):
# 方式二
@method_decorator(a) # 所有请求都触发装饰器
def dispatch(self, request, *args, **kwargs): # 重写父类方法
print("请求前的操作")
ret = super().dispatch(request, *args,**kwargs)
print("请求后的操作")
return ret
# 方式三
@method_decorator(a) # get 请求触发装饰器
def get(self,request):
return render(request,"index.html")
def post(self,request):
return HttpResponse("登陆成功")
请求方法
request对象
当一个页面被请求时,Django就会创建一个包含本次请求原信息(请求报文中的请求行、首部信息、内容主体等)的HttpRequest对象。Django会将这个对象自动传递给响应的视图函数,一般视图函数约定俗成地使用 request 参数承接这个对象。
from django.shortcuts import render,HttpResponse
# Create your views here.
def login(request):
print(request.path) # 纯路径
print(request.path_info) # 纯路径
print(request.get_full_path()) # 全部路径,不含ip地址和端口号
print(request.META) # 请求头相关数据,是一个字典
print(request.method) # 获取请求的类型(GET、POST)
print(request.GET.get("a")) # 获取GTE请求的数据
print(request.POST.get("a")) # 获取POST请求的数据
print(request.body) # 拿到POST请求的数据bytes类型
return HttpResponse('ok')
响应方法
HttpRequest
与由Django自动创建的HttpRequest对象相比,HttpResponse对象需要手动在每个视图实例化,填充和返回一个HttpResponse。HttpResponse类位于django.http模块中。
from django.shortcuts import HttpResponse
# Create your views here.
def index(request):
return HttpResponse("这是首页")
JsonResponse
JsonResponse可以将数据进行序列化,ajax在接受到数据时会自动进行反序列化。序列化非字典类型数据时需要指定safe=False
from django.http import JsonResponse
if request.method == "GET":
return render(request,"login.html")
else:
uid = request.POST.get("uid")
pwd = request.POST.get("pwd")
dic = {"stats":None,"msg":None}
print(uid)
print(pwd)
if uid == "1" and pwd == "1":
dic["stats"] = 100
dic["msg"] = "登陆成功"
else:
dic["stats"] = 101
dic["mas"] = "登陆失败"
# dic = json.dumps(dic,ensure_ascii=False)
# return HttpResponse(dic,content_type='application/json')
return JsonResponse(dic) # 通过JsonResponse将数据自动序列化
return JsonResponse(dic,safe=False) # 非字典类型需要设置safe=False
$("#bu").click(function () {
var uid = $("#uid").val();
var pwd = $("#pwd").val();
$.ajax({
url: "/login/",
type: "post",
data: {"uid":uid,"pwd":pwd},
headers: {"X-CSRFToken": $.cookie("csrftoken")},
success: function (res) {
// var res = JSON.parse(res); //-- json.loads()
console.log(res); // 得到的结果就是反序列化的结果可以直接取值
if(res.stats === 100){
location.href="/index/"
}else {
$("span").text(res.msg)
}
}
})
});
render
结合一个给定的模板和一个给定的上下文字典,并返回一个渲染后的 HttpResponse 对象。
返回时可以以键值对的形式携带数据返回
from django.shortcuts import render
# Create your views here.
def index(request):
return render(request,"index.html",{"data":"数据"})
redirect
默认返回一个临时的重定向;传递permanent=True 可以返回一个永久的重定向。
from django.shortcuts import render,redirect
# Create your views here.
def index(request):
return redirect("http://www.baidu.com") # 重定向