一.FBV
1.基本使用
概念:基于函数的视图函数(function base view)
创建主路由:
url(r'^fbv/',include('FbvApp.urls')),
创建子路由:
url(r'^animal/',views.animal),
创建模型并进行迁移:
class Animal(models.Model):
name = models.CharField(max_length=32)
age = models.IntegerField(default=1)
sex = models.NullBooleanField(default=0)
class Meta:
db_table = 'animal'
添加数据:
生成视图函数:
restful:表征性状态转移,就是在浏览器的地址栏上,不会看到他的动作,而是根据请求方式的不同,来执行不同的业务逻辑
@csrf_exempt
def animal(request):
if request.method == 'GET':
data = {
'method': 'get',
}
return JsonResponse(data=data)
elif request.method == 'POST':
data = {
'method': 'post'
}
return JsonResponse(data=data)
elif request.method == 'PUT':
data = {
'method': 'put'
}
return JsonResponse(data=data)
elif request.method == 'PATCH':
data = {
'method': 'patch'
}
return JsonResponse(data=data)
elif request.method == 'DELETE':
data = {
'method': 'delete'
}
return JsonResponse(data=data)
使用postman进行测试,运行结果:
get请求方式:
post请求方式:
put请求方式:
patch请求方式:
delete请求方式:
注意:请求方式必须大写
总结:(1)需要判断请求方式 (2)序列化,反序列化难度大
2.序列化问题
下面以get请求方式为例:
def animal(request):
if request.method == 'GET':
animal = Animal.objects.first()
data = {
'method': 'get',
'animal': animal
}
return JsonResponse(data=data)
运行结果:
我们会发现报错,Animal不是json序列化
解决方法:
在模型中定义to_dict方法:
# 当对象调用了to_dict方法之后,那么会返回一个字典
def to_dict(self):
return {'name': self.name, 'age': self.age, 'sex': self.sex}
在视图函数中调用to_dict方法:
def animal(request):
if request.method == 'GET':
animal = Animal.objects.first()
data = {
'method': 'get',
'animal':animal.to_dict()
}
return JsonResponse(data=data)
运行结果:
上面是解决一个对象序列化问题的方法,那如果是一个列表呢???
解决方法:
def animal(request):
if request.method == 'GET':
animal_list = Animal.objects.all()
# 不能直接返回一个列表中的元素是对象的列表
a_list = []
for animal in animal_list:
a_list.append(animal.to_dict())
data = {
'method': 'get',
'a_list': a_list
}
return JsonResponse(data=data)
运行结果:
二.CBV
1.基本使用
概念:基于类的视图函数(class base view)
创建主路由:
url(r'^cbv/',include('CbvApp.urls')),
创建子路由:
原来 url(r’^animal/’,views.animal)
cbv url(r’^animal1/’,views.类)
# as_view默认情况下是没有(),需要自己手动添加
url(r'^animalView/',views.AnimalView.as_view()),
生成视图函数:
# 类视图函数的类 一定要继承View
class AnimalView(View):
def get(self,request):
data = {
'msg':'get'
}
return JsonResponse(data=data)
def post(self,request):
data = {
'msg': 'post'
}
return JsonResponse(data=data)
def put(self,request):
data = {
'msg': 'put'
}
return JsonResponse(data=data)
def patch(self,request):
data = {
'msg': 'patch'
}
return JsonResponse(data=data)
def delete(self,request):
data = {
'msg': 'delete'
}
return JsonResponse(data=data)
运行结果:
get请求方法:
post请求方法:
无论是在post函数上加装饰器还是在类上加装饰器,我们会发现都不行,我们暂时注释掉csrf的中间件
注意:(1)书写请求方式对应的函数, 函数名就是请求方式名字的小写,注意只能小写, 方法中的参数必须书写request
(2)不能在函数或类前加csrf装饰器
总结:(1)不需要判断请求方式 (2)序列化,反序列化难度大
2.序列化问题
创建子路由:
url(r'^animalView1/',views.AnimalView1.as_view()),
生成视图函数:
class AnimalView1(View):
def get(self,request):
animal = Animal.objects.first()
data = {
'msg':'get',
'animal':animal
}
return JsonResponse(data=data)
运行结果:
这里的解决方法与FBV解决序列化的方式一致:
class AnimalView1(View):
def get(self,request):
animal = Animal.objects.first()
data = {
'msg':'get',
'animal':animal.to_dict()
}
return JsonResponse(data=data)
运行结果:
class AnimalView1(View):
def get(self,request):
animal_list = Animal.objects.all()
a_list =[]
for animal in animal_list:
a_list.append(animal.to_dict())
data = {
'msg':'get',
'a_lsit':a_list
}
return JsonResponse(data=data)
运行结果:
3.TemplateView
作用:执行类视图然后跳转到指定模板。
创建子路由:
url(r'^testTemView/',views.TestTemView.as_view()),
生成视图函数:
# 跳转到一个模板
class TestTemView(TemplateView):
template_name = 'testTemView.html'
创建’testTemView.html模板:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
天气不错嘛
</body>
</html>
运行结果:
视图函数如上面写就能运行成功,是不是很神奇?还有更神奇,更简单粗暴的
修改子路由:
url(r'^testTemView/',views.TestTemView.as_view(template_name='testTemView.html')),
视图函数:
class TestTemView(TemplateView):
pass
运行结果:
、
总结:
1.继承TemplateView
不需要写get方法,因为TemplateView里重写了get方法
2.实现方式:
(1)在类视图中指定 template_name=‘hello.html’
(2)在as_view中书写template_name属性
3.实现原理:
(1)TemplateView继承了TemplateResponseMixin, ContextMixin, View
(2)TemplateView类中定义了get方法,该方法调用了TemplateResponseMixin的render_to_response方法
4.应用场景:单纯的跳转页面
5.注意:单纯的跳转页面,不能进行传参。
4.ListView
作用:执行类视图然后跳转到指定模板并且传递数据
创建子路由:
url(r'^testListView/',views.TestListView.as_view()),
生成视图函数:
class TestListView(ListView):
template_name = 'testListView.html'
创建testListView.html文件:
<body>
天道有轮回,苍天饶过谁。
</body>
运行结果:
之所以报错的原因,是TestListView的意义不仅仅在于渲染页面还要传参
那我们现在来传个参:
class TestListView(ListView):
template_name = 'testListView.html'
model = Animal
<body>
天道有轮回,苍天饶过谁。
<ul>
{% for animal in animal_list %}
<li>{{ animal.name }}</li>
{% endfor %}
</ul>
</body>
</html>
运行结果:
另一种方式:
class TestListView(ListView):
template_name = 'testListView.html'
# model = Animal
queryset = Animal.objects.all()
<body>
天道有轮回,苍天饶过谁。
<ul>
{% for animal in animal_list %}
<li>{{ animal.name }}</li>
{% endfor %}
</ul>
<hr>
<ul>
{% for object in object_list %}
<li>{{ object.name }}</li>
{% endfor %}
</ul>
</body>
运行结果:
实现原理:
负责跳转页面:
ListView继承了MultipleObjectTemplateResponseMixin,
MultipleObjectTemplateResponseMixin继承了TemplateResponseMixin,
在TemplateResponseMixin中有render_to_response方法
负责传递参数:
ListView继承了BaseListView,
BaseListView继承了MultipleObjectMixin,
MultipleObjectMixin中有model和queryset的属性和get_queryset方法
应用场景:
查询 eg:list 分页
5.DetailView
作用:执行类视图跳转到指定模板,传递一个数据
创建子路由:
#单一实例,DetailView必须传递一个id,路由关键字参数
url(r'^TestDetailView/(?P<pk>\d+)/',views.TestDetailView.as_view()),
生成视图函数:
class TestDetailView(DetailView):
template_name = 'testDetailView.html'
# model = Animal
queryset = Animal.objects.all()
创建testDetailView.html文件:
<body>
DetailView测试
<hr>
{{ animal.name }}
<hr>
{{ object.name }}
</body>
运行结果:
实现原理:
负责跳转页面
DetailView继承了SingleObjectTemplateResponseMixin,
SingleObjectTemplateResponseMixin继承了TemplateResponseMixin,
TemplateResponseMixin有一个render_to_response方法
负责传递参数
DetailView继承了BaseDetailView,
BaseDetailView继承了SingleObjectMixin,
SingleObjectMixin中有model,queryset,get_queryset方法
应用场景:修改,点击修改的时候,然后传递id参数,获取到对象,在表单中遍历
总结类视图:
View适用于前后端分离,方法的返回值是json数据
TemplateView,ListView, DetailView适用全栈开发
TemplateView:跳转页面
ListView:跳转页面,传递数据
DetailView:跳转页面,传递单个数据