视图函数

  • 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
  • 注册时使用的as_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方法

    • 获取接口信息,可以获取到接口都允许什么接口


发送options请求,可以看到允许接收的请求。

简化流程

  • as_view
  • dispatch
  • 调用实现请求方法对应的函数名
最后修改:2024 年 03 月 13 日
如果觉得我的文章对你有用,请随意赞赏