CBV和APIView流程

本文介绍如何通过 Django REST framework 实现 RESTful API 的基本功能,包括安装配置、URL 设计、请求处理流程等,并对比了普通 View 和 APIView 的区别。

    restframework安装   

1.下载pip install djangorestframework
2.使用时:在INSTALLED_APPS加入"rest_framework"
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'app01.apps.App01Config',
    "rest_framework"
]
 
 

restful协议

url
一切皆资源
book / add
books
book / 1 / change
book / 1 / delete
在restful中:
books - ------get  :查询所有书籍 - ------- 返回的查询的所有书籍
books - ------post :添加一本书籍 - ------- 返回添加书籍
books / 1 - ------get :查看某本书籍 - ------- 返回这本书籍
books / 1 - ------put / patch :编辑某本书籍 - ---返回编辑后的书籍
books / 1 - ------delete :删除某本书籍 - ---返回空

        CBV流程解析     

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^book/', views.BookView.as_view()),
    url(r'^book/(\d+)', views.BookDetailView.as_view()),
]

请求走到url中,怎么执行的?

1.执行View中的as_view,返回结果view 
2.执行View中的view,返回结果self.dispatch,self为自定义的类的对象,自定义类中无dispatch方法
就执行View中的dispatch
3.执行View中的dispatch,利用反射执行对应的请求函数
class BookView(View):
    def get(self,request):
        return HttpResponse("get.........")
    def post(self,request):
        return HttpResponse("post........")
1.请求找到 url(r'^book/', views.BookView.as_view())这条路由,执行views.BookView.as_view()
views.BookView是我们在views中自定义的类,在这里调用了as_view,那么as_view应该是类中的属性或方法,
而自定义的类中没有as_view,应该去其父类中查找
去View中查找as_view,查看源码及进行分析
 
 
class View(object):
 @classonlymethod
    def as_view(cls, **initkwargs):
        """
        Main entry point for a request-response process.
        """
        for key in initkwargs:
            if key in cls.http_method_names:
                raise TypeError("You tried to pass in the %s method name as a "
                                "keyword argument to %s(). Don't do that."
                                % (key, cls.__name__))
            if not hasattr(cls, key):
                raise TypeError("%s() received an invalid keyword %r. as_view "
                                "only accepts arguments that are already "
                                "attributes of the class." % (cls.__name__, key))

        def view(request, *args, **kwargs):
            self = cls(**initkwargs)
            if hasattr(self, 'get') and not hasattr(self, 'head'):
                self.head = self.get
            self.request = request
            self.args = args
            self.kwargs = kwargs
            return self.dispatch(request, *args, **kwargs)
        view.view_class = cls
        view.view_initkwargs = initkwargs

        # take name and docstring from class
        update_wrapper(view, cls, updated=())
        # and possible attributes set by decorators
        # like csrf_exempt from dispatch
        update_wrapper(view, cls.dispatch, assigned=())
        return view
View Code
as_view是类方法,views.BookView.as_view()的结果是view
url(r'^book/', views.BookView.as_view()),相当于 url(r'^book/', view) 根据函数式路由猜测views应返回一个函数名
url(r'^book/', view) 一旦用户访问book 执行的是view(request),view返回了什么,在页面上就应该显示什么
2.执行View中的view:
view的源码
def view(request, *args, **kwargs):
            self = cls(**initkwargs)
            if hasattr(self, 'get') and not hasattr(self, 'head'):
                self.head = self.get
            self.request = request
            self.args = args
            self.kwargs = kwargs
            return self.dispatch(request, *args, **kwargs)
view的执行结果是return self.dispatch(request),self是BookView的对象,去找dispatch方法,如果未定义,就去找父类View中的dispatch
3.View中的dispatch
def dispatch(self, request, *args, **kwargs):
        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)
所有的请求方式:http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']
当前请求在请求方式中的话,就利用反射调用请求方法
url(r'^books/', view), # 一旦用户访问books 执行的是view(request)======self.dispatch(request)========self.get(request)

1.BookView中无dispatch,执行View中的dispatch
如果是get/post请求,就执行BookView中的get/post

class BookView(View):
    def get(self,request):
        return HttpResponse("get.........")
    def post(self,request):
        return HttpResponse("post........")

2.BookView中有dispatch,则不再执行View中的dispatch

 

class BookView(View):
    def dispatch(self, request, *args, **kwargs):
        print("dispatch......")
    def get(self,request):
        return HttpResponse("get.........")
    def post(self,request):
        return HttpResponse("post........")

 

无论是post还是get请求,均不会执行BookView中的get/post方法。因为BookView中有dispatch则不会执行
View中的dispatch。在BookView中dispatch没设置返回值,页面会报错,在服务器后端显示dispatch.......

 

3.即执行BookView中的dispatch又执行Views中的dispatch

 

class BookView(View):
    def dispatch(self, request, *args, **kwargs):
        print("dispatch.......")
        ret=super().dispatch(request, *args, **kwargs)
        return  ret
    def get(self,request):
        return HttpResponse("get.........")
    def post(self,request):
        return HttpResponse("post........")

 

好处:可以添加额外的功能

        APIview流程      

1.执行APIView中的as_view,返回的结果super(APIView, cls).as_view(**initkwargs)
2.执行View中的as_view,返回结果view
3.执行View中的view,返回结果self.dispatch,self为自定义的类的对象,自定义类中无dispatch方法
就执行APIview中的dispatch
4.执行APIview中的dispatch,利用反射执行对应得请求函数,同时将原生得request进行封装

 

1.在url中设计两条路由:

url(r'^book/', views.BookView.as_view()),
url(r'^book/(\d+)', views.BookDetailView.as_view()),
url(r'^book/', views.BookView.as_view())完成查询所有书籍和添加书籍的操作
url(r'^book/(\d+)', views.BookDetailView.as_view())完成查看某本书籍,编辑某本书籍和删除某本书籍的操作

2.使用APIView

from rest_framework.views import APIView
class BookView(APIView):
    def get(self,request):
        book_obj=models.Book.objects.all()
        #将每个对象都取出来,放到列表中,序列化后返回
        temp=[]
        for obj in book_obj:
            temp.append({
                "pk":obj.pk,
                "title":obj.title
            })
        return HttpResponse(json.dumps(temp))
    def post(self,request):
        return HttpResponse("post........")
1.在执行url时,执行views.BookView.as_view(), BookView中无as_view
去父类APIView中查找
class APIView(View):
    @classmethod
    def as_view(cls, **initkwargs):
         if isinstance(getattr(cls, 'queryset', None), models.query.QuerySet):
            def force_evaluation():
                raise RuntimeError(
                    'Do not evaluate the `.queryset` attribute directly, '
                    'as the result will be cached and reused between requests. '
                    'Use `.all()` or call `.get_queryset()` instead.'
                )
            cls.queryset._fetch_all = force_evaluation
        view = super(APIView, cls).as_view(**initkwargs)
        view.cls = cls
        view.initkwargs = initkwargs
        return csrf_exempt(view)
views.BookView.as_view()的结果是view,查看view
2. view的值是View中as_view的返回值
view = super(APIView, cls).as_view(**initkwargs)
执行APIView父类View中as_view方法:
class View(object):
    @classmethod
    def as_view(cls, **initkwargs):
      def as_view(cls, **initkwargs):
        pass
        def view(request, *args, **kwargs):
            self = cls(**initkwargs)
            if hasattr(self, 'get') and not hasattr(self, 'head'):
                self.head = self.get
            self.request = request
            self.args = args
            self.kwargs = kwargs
            return self.dispatch(request, *args, **kwargs)
        view.view_class = cls
        view.view_initkwargs = initkwargs
        return view
3.执行View中的view方法,结果执行self.dispatch(request, *args, **kwargs),
BookView无dispatch方法,执行APIView中的dispatch方法
4. 执行APIView中的dispatch方法
class APIView(View):
def dispatch(self, request, *args, **kwargs):
     self.args = args
        self.kwargs = kwargs
        request = self.initialize_request(request, *args, **kwargs)
        self.request = request
        self.headers = self.default_response_headers  # deprecate?
        try:
            self.initial(request, *args, **kwargs)

            # Get the appropriate handler method
            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

            response = handler(request, *args, **kwargs)
        except Exception as exc:
            response = self.handle_exception(exc)
        self.response = self.finalize_response(request, response, *args, **kwargs)
        return self.response
try中的代码和View中dispatch的代码相同,均是利用反射执行对应的请求函数
class View(object):
    def dispatch(self, request, *args, **kwargs):
        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)
View Code
 
 
5.封装APIView中dispatch方法中的request
但两者的request是不同的,View中dispatch的request是原生的request
而APIView中的dispatch方法中后续使用的request是封装过的request
def dispatch(self, request, *args, **kwargs):
     request = self.initialize_request(request, *args, **kwargs)
     self.request = request
在dispatch中,将原生的request作为initialize_request方法中的参数,执行后返回一个Request对象,将封装后的这个对象赋给request
之后使用的request都是封装后的request
def initialize_request(self, request, *args, **kwargs):
    parser_context = self.get_parser_context(request)
        return Request(
            request,  #原生类
            parsers=self.get_parsers(),
            authenticators=self.get_authenticators(),
            negotiator=self.get_content_negotiator(),
            parser_context=parser_context
        )
查看Request这个类:
class Request(object):
        self._request = request
        self.parsers = parsers or ()
        self.authenticators = authenticators or ()
        self.negotiator = negotiator or self._default_negotiator()
        self.parser_context = parser_context
        self._data = Empty
        @property
        def query_params(self):
            return self._request.GET
其中的_request属性的值就是原生的类,可通过调用这个属性来查看原生类的值
 
 

1.在发送get时,打印接收值

from rest_framework.views import APIView
class BookView(APIView):
    def get(self,request):
        print(request.GET)
        print(request._request.GET)
        print(request.query_params)
        return HttpResponse("ok"<QueryDict: {'title': ['go']}>
<QueryDict: {'title': ['go']}>
<QueryDict: {'title': ['go']}>
query_params和_request.GET是一样的

2.使用post请求

使用post请求时,原生的request只能解析urlencode数据使用封装后的request.data有着多种解析器
使用urlencoded解析:
def post(self,request):
    print("request.Post:",request.POST)
    print("request.data:", request.data)
     #获取值:
    print("request.data:", request.data["title"])
    return HttpResponse("post........")
request.Post: <QueryDict: {'title': ['c++']}>
request.data: <QueryDict: {'title': ['c++']}>


其它解析:
request.Post: <QueryDict: {}>
request.data: {'title': 'c++'}
request.data: c++

 

转载于:https://www.cnblogs.com/zgf-666/p/9199712.html

04-01
### 关于NM CBV的概念 在网络管理(Network Management, NM)协议中,CBV代表Control Bit Vector(控制位向量)。它是一个字节长度的数据字段,用于表示网络管理状态信息。具体来说,CBV中的每一位都可以用来传递特定的网络管理信号或状态标志[^1]。 然而,“CBV”在不同的上下文中可能具有完全不同的含义。例如,在Django框架中,CBV指的是Class-Based Views(基于类的视图),这是一种通过定义Python类来实现HTTP请求处理的方式[^2]。尽管两者都使用了“CBV”的缩写,但它们的应用领域技术背景完全不同。 如果讨论的是编程或框架环境下的NM CBV,则可能是某种自定义扩展或者误解。目前没有公开资料表明存在名为“NM CBV”的编程概念或框架组件。因此,这里的“NM CBV”更有可能是指AUTOSAR NM协议中的CBV字段,而非一种具体的编程技术。 --- ### AUTOSAR NM中的CBV详解 在AUTOSAR标准下,NM消息的数据段包含了多个部分,其中CBV是最核心的部分之一。以下是其主要作用: - **源节点地址ID**:标识发送此NM消息的ECU节点。 - **CBV(Control Bit Vector)**:这是一个8比特的字段,每一位都有特定的意义,通常用于指示当前节点的状态或其他网络管理相关信息。例如,某些位可能会被用来标记睡眠模式、唤醒请求或者其他同步事件。 - **数据域**:这部分允许开发者根据实际需求定义额外的有效载荷。它可以包括两字节的用户数据以及四字节的PNC(Partial Network Coordination)位向量。 #### CBV的具体结构 虽然未提供详细的位分配方案,但在典型的实现中,CBV的各位可能有以下用途: - 某些固定位置的比特用于通用的功能标志(如活动/休眠状态)。 - 剩余的比特则可以根据项目需求灵活配置。 --- ### Django中的CBV对比分析 相比之下,Django中的CBV是一种面向对象的设计方式,旨在简化Web应用开发过程。它的基本原理是将HTTP方法映射到类的方法上,从而使得代码更加模块化可重用。例如,`get()` `post()` 方法分别对应GETPOST类型的HTTP请求[^4]。 下面是一段简单的Django CBV示例代码: ```python from django.views import View from django.http import HttpResponse class ExampleView(View): def get(self, request): return HttpResponse("这是GET请求的响应") def post(self, request): return HttpResponse("这是POST请求的响应") ``` 需要注意的是,上述代码与AUTOSAR NM中的CBV没有任何关联。二者仅共享相同的字母组合作为名称缩写。 --- ### 结论 综上所述,“NM CBV”并非指代任何已知的编程范式或软件架构组成部分;相反,它是汽车电子通信领域内的术语,特指AUTOSAR NM协议里的控制位向量。而Django及其他现代Web框架所采用的CBV则是另一套独立的技术体系,专注于提升后端服务构建效率。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值