视图函数
FBV
- function base view(基于函数的视图)
CBV
- class base view(基于类的视图)
CBV
CBV简单案例
新建一个CBV项目:
Python manage.py startapp CBV
新建urls,并且在总urls内注册:
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^app/', include('App.urls', namespace='app')),
url(r'^api/', include('api.urls', namespace='api')),
url(r'^cbv/', include('CBV.urls', namespace='cbv')),
]
views.py:
from django.http import HttpResponse
from django.shortcuts import render
from django.views import View
class HelloCBV(View):
def get(self, request):
return HttpResponse("哈哈哈")
以往使用函数来写视图,这次使用class类来创建视图,自己创建的视图需要继承django中的View.
在cbv.urls.py中注册该views:
from django.conf.urls import url
from CBV import views
urlpatterns = [
url(r'^hello/', views.HelloCBV.as_view(), name='hello'),
]
注意第6行多出了as_view().
测试:
可以看到get访问成功。
但是当使用Post请求该链接时,显示:
可以看到显示405请求方法不支持,因为我们在类中定义的就是get方法,只能接受get请求。
如果想接受POST请求,只需要定义post请求即可:
views.py:
class HelloCBV(View):
def get(self, request):
return HttpResponse("哈哈哈")
def post(self, request):
return HttpResponse("666")
使用postman发送post请求:
可以看到发送成功。
类比到其他请求类型,都是直接def 对应的方法即可。
用CBV改写Book视图
例如之前的Book视图,我们可以对其进行改写。
首先将models迁移,到cbv下的models中,在这之前需要先将,cbv.models.py在settings.py中注册,是为了照顾其他模块。
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'App.apps.AppConfig',
'api',
'CBV',
]
然后迁移数据库
views.py:
class BooksCBV(View):
def get(self, request):
books_list = Book.objects.all() # 这个只是一个查询集,不符合json的格式
books_list_json = []
for book in books_list:
books_list_json.append(book.to_dict())
print(books_list_json)
data = {
'status': 200,
'msg': 'ok',
'data': books_list_json
}
return JsonResponse(data=data)
def post(self, request):
# 从前端获取POST请求中的书名,价钱
print(request.body)
b_name = request.POST.get('b_name')
b_price = request.POST.get('b_price')
# 获取完信息之后,新建Book对象进行存储
book = Book()
book.b_name = b_name
book.b_price = b_price
book.save()
# 然后返回json数据,这里比较麻烦的是将模型变成字典数据
data = {
'status': 201,
'mag': 'add success',
'data': book.to_dict()
}
return JsonResponse(data=data, status=201)
urls.py:
from django.conf.urls import url
from CBV import views
urlpatterns = [
url(r'^hello/', views.HelloCBV.as_view(), name='hello'),
url(r'^books/', views.BooksCBV.as_view(), name='books'),
]
测试:
post:
get:
优点
- 相比于之前的FBV需要使用if判断请求类型,CBV可以直接定义对用的请求方式名即可。
- 在使用不匹配的请求访问url报错时,直接返回405,不会返回内部错误报错。
- 可以进行类的继承调用,实现代码复用(例如很多模块执行前需要验证用户信息)
类视图
- CBV
- 继承自view
数据走向
从最外层开始走,用户的请求,先到服务器uwsgi,然后到达根路由,然后到达CBV里面的urls路由中,然后进行匹配,例如匹配到url中的Book类函数。
urlpatterns = [ url(r'^hello/', views.HelloCBV.as_view(), name='hello'), url(r'^books/', views.BooksCBV.as_view(), name='books'), ]
可以看到类视图在urls注册时的方法和之前有所改变,多了一个.as_view().
as_view源码分析
可以看到View继承自object
并且有一个列表存放各种请求类型名。
初始化方法,接受关键字参数。
- 52:入口先判断不能将请求方法的名字作为参数的名字。
- 56:只能接收views.py中已经声明存在的参数属性。
- 62:创建了类视图的对象
61:定义了views
- 63:默认只要支持get,就支持head请求
- 65,66,67:用cls将传递的属性记录下来
68:调用dispatch方法
- dispatch:
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: handler = getattr(self, request.method.lower(), self.http_method_not_allowed) else: handler = self.http_method_not_allowed return handler(request, *args, **kwargs)
- 5:如果请求方法在允许列表中 - 6:就从自己的对象中,获取方法名字中小写的属性,如果没有找到就使用self.http_method_not_allowed默认参数 - 7:如果请求方法不在允许列表中 - 8:直接http_method_not_allowed - 9:将参数返回给调用函数
默认实现了options方法
- 获取接口信息,可以获取到接口都允许什么接口
简化流程
- as_view
- dispatch
- 调用实现请求方法对应的函数名
此处评论已关闭