Django FBV, function base view  视图里使用函数处理请求

url

1
url(r‘^users/‘, views.users),

views

1
2
3
4
5
from django.shortcuts import HttpResponse
import json
def users(request):
    user_list = ['lcg','superman']
    return HttpResponse(json.dumps((user_list)))

Django CBV, class base view 视图里使用类处理请求

url

1
url(r'^students/', views.StudentsView.as_view()),

views

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from django.shortcuts import HttpResponse
from django.views import View
   
class StudentsView(View):
   
    def get(self,request,*args,**kwargs):
        return HttpResponse('GET')
   
    def post(self, request, *args, **kwargs):
        return HttpResponse('POST')
   
    def put(self, request, *args, **kwargs):
        return HttpResponse('PUT')
   
    def delete(self, request, *args, **kwargs):
        return HttpResponse('DELETE')

注意:

  • cbv定义类的时候必须要继承view
  • 在写url的时候必须要加as_view
  • 类里面使用form表单提交的话只有get和post方法
  • 类里面使用ajax发送数据的话支持定义以下很多方法
    restful规范:
    'get'获取数据, 'post'创建新数据, 'put'更新, 'patch'局部更新, 'delete'删除, 'head', 'options', 'trace'

CBV原理:继承,反射。

点进StudentView继承的View可以看到如下代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
class View(object):
    """
    Intentionally simple parent class for all views. Only implements
    dispatch-by-method and simple sanity checking.
    """
 
    http_method_names = ['get''post''put''patch''delete''head''options''trace']
 
    def __init__(self**kwargs):
        """
        Constructor. Called in the URLconf; can contain helpful extra
        keyword arguments, and other things.
        """
        # Go through keyword arguments, and either save their values to our
        # instance, or raise an error.
        for key, value in six.iteritems(kwargs):
            setattr(self, key, value)
 
    @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
 
    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)
 
    def http_method_not_allowed(self, request, *args, **kwargs):
        logger.warning(
            'Method Not Allowed (%s): %s', request.method, request.path,
            extra={'status_code'405'request': request}
        )
        return http.HttpResponseNotAllowed(self._allowed_methods())
 
    def options(self, request, *args, **kwargs):
        """
        Handles responding to requests for the OPTIONS HTTP verb.
        """
        response = http.HttpResponse()
        response['Allow'= ', '.join(self._allowed_methods())
        response['Content-Length'= '0'
        return response
 
    def _allowed_methods(self):
        return [m.upper() for in self.http_method_names if hasattr(self, m)]

View类里面的部分如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
@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

上面实质上是路由里面的那里写的as_view ,返回值是view 而view方法返回的是self.dispath。

1
http_method_names = ['get''post''put''patch''delete''head''options''trace']

该列表定义了八种客户端对服务端的访问方式

从路由到视图这个过程,会自动初始化该StudentView对象,并执行在类里写好的诸多方法,其中较为关键的是dispatch方法(通过as_view)。

1
2
3
4
5
6
7
8
9
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)

函数主要是对客户端发来的请求进行分类处理,按照对应的方法去处理,也就是我们在FBV函数里经常写到的request.method。

也就是说,继承自View的类下的所有的方法本质上都是通过dispatch这个函数反射执行,如果想要在执行get或post方法前执行其他步骤,可以重写dispatch。

Django REST framework CBV

url

1
url(r'^students/', views.StudentsView.as_view()),

views

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from rest_framework.views import APIView
from django.shortcuts import HttpResponse
 
 
class StudentsView(APIView):
 
    def get(self, request, *args, **kwargs):
        return HttpResponse('GET')
 
    def post(self, request, *args, **kwargs):
        return HttpResponse('POST')
 
    def put(self, request, *args, **kwargs):
        return HttpResponse('PUT')
 
    def delete(self, request, *args, **kwargs):
        return HttpResponse('DELETE')

rest_framework.views里面导入的APIView实际上是对Django的View的一个封装

Django REST framework CBV的原理与Django的原理是一样的。路由里面的那里写的as_view ,返回值是view 而view方法返回的是self.dispath。APIView基础了View,并且重写了dispath方法。APIView中的dispatch方法有很多的功能

class APIView(View):

    # The following policies may be set at either globally, or per-view.
renderer_classes = api_settings.DEFAULT_RENDERER_CLASSES
parser_classes = api_settings.DEFAULT_PARSER_CLASSES
authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES
throttle_classes = api_settings.DEFAULT_THROTTLE_CLASSES
permission_classes = api_settings.DEFAULT_PERMISSION_CLASSES
content_negotiation_class = api_settings.DEFAULT_CONTENT_NEGOTIATION_CLASS
metadata_class = api_settings.DEFAULT_METADATA_CLASS
versioning_class = api_settings.DEFAULT_VERSIONING_CLASS # Allow dependency injection of other settings to make testing easier.
settings = api_settings schema = DefaultSchema() @classmethod
def as_view(cls, **initkwargs):
"""
Store the original class on the view function. This allows us to discover information about the view when we do URL
reverse lookups. Used for breadcrumb generation.
"""
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 # Note: session based authentication is explicitly CSRF validated,
# all other authentication is CSRF exempt.
return csrf_exempt(view) @property
def allowed_methods(self):
"""
Wrap Django's private `_allowed_methods` interface in a public property.
"""
return self._allowed_methods() @property
def default_response_headers(self):
headers = {
'Allow': ', '.join(self.allowed_methods),
}
if len(self.renderer_classes) > 1:
headers['Vary'] = 'Accept'
return headers def http_method_not_allowed(self, request, *args, **kwargs):
"""
If `request.method` does not correspond to a handler method,
determine what kind of exception to raise.
"""
raise exceptions.MethodNotAllowed(request.method) def permission_denied(self, request, message=None):
"""
If request is not permitted, determine what kind of exception to raise.
"""
if request.authenticators and not request.successful_authenticator:
raise exceptions.NotAuthenticated()
raise exceptions.PermissionDenied(detail=message) def throttled(self, request, wait):
"""
If request is throttled, determine what kind of exception to raise.
"""
raise exceptions.Throttled(wait) def get_authenticate_header(self, request):
"""
If a request is unauthenticated, determine the WWW-Authenticate
header to use for 401 responses, if any.
"""
authenticators = self.get_authenticators()
if authenticators:
return authenticators[0].authenticate_header(request) def get_parser_context(self, http_request):
"""
Returns a dict that is passed through to Parser.parse(),
as the `parser_context` keyword argument.
"""
# Note: Additionally `request` and `encoding` will also be added
# to the context by the Request object.
return {
'view': self,
'args': getattr(self, 'args', ()),
'kwargs': getattr(self, 'kwargs', {})
} def get_renderer_context(self):
"""
Returns a dict that is passed through to Renderer.render(),
as the `renderer_context` keyword argument.
"""
# Note: Additionally 'response' will also be added to the context,
# by the Response object.
return {
'view': self,
'args': getattr(self, 'args', ()),
'kwargs': getattr(self, 'kwargs', {}),
'request': getattr(self, 'request', None)
} def get_exception_handler_context(self):
"""
Returns a dict that is passed through to EXCEPTION_HANDLER,
as the `context` argument.
"""
return {
'view': self,
'args': getattr(self, 'args', ()),
'kwargs': getattr(self, 'kwargs', {}),
'request': getattr(self, 'request', None)
} def get_view_name(self):
"""
Return the view name, as used in OPTIONS responses and in the
browsable API.
"""
func = self.settings.VIEW_NAME_FUNCTION
return func(self.__class__, getattr(self, 'suffix', None)) def get_view_description(self, html=False):
"""
Return some descriptive text for the view, as used in OPTIONS responses
and in the browsable API.
"""
func = self.settings.VIEW_DESCRIPTION_FUNCTION
return func(self.__class__, html) # API policy instantiation methods def get_format_suffix(self, **kwargs):
"""
Determine if the request includes a '.json' style format suffix
"""
if self.settings.FORMAT_SUFFIX_KWARG:
return kwargs.get(self.settings.FORMAT_SUFFIX_KWARG) def get_renderers(self):
"""
Instantiates and returns the list of renderers that this view can use.
"""
return [renderer() for renderer in self.renderer_classes] def get_parsers(self):
"""
Instantiates and returns the list of parsers that this view can use.
"""
return [parser() for parser in self.parser_classes] def get_authenticators(self):
"""
Instantiates and returns the list of authenticators that this view can use.
"""
return [auth() for auth in self.authentication_classes] def get_permissions(self):
"""
Instantiates and returns the list of permissions that this view requires.
"""
return [permission() for permission in self.permission_classes] def get_throttles(self):
"""
Instantiates and returns the list of throttles that this view uses.
"""
return [throttle() for throttle in self.throttle_classes] def get_content_negotiator(self):
"""
Instantiate and return the content negotiation class to use.
"""
if not getattr(self, '_negotiator', None):
self._negotiator = self.content_negotiation_class()
return self._negotiator def get_exception_handler(self):
"""
Returns the exception handler that this view uses.
"""
return self.settings.EXCEPTION_HANDLER # API policy implementation methods def perform_content_negotiation(self, request, force=False):
"""
Determine which renderer and media type to use render the response.
"""
renderers = self.get_renderers()
conneg = self.get_content_negotiator() try:
return conneg.select_renderer(request, renderers, self.format_kwarg)
except Exception:
if force:
return (renderers[0], renderers[0].media_type)
raise def perform_authentication(self, request):
"""
Perform authentication on the incoming request. Note that if you override this and simply 'pass', then authentication
will instead be performed lazily, the first time either
`request.user` or `request.auth` is accessed.
"""
request.user def check_permissions(self, request):
"""
Check if the request should be permitted.
Raises an appropriate exception if the request is not permitted.
"""
for permission in self.get_permissions():
if not permission.has_permission(request, self):
self.permission_denied(
request, message=getattr(permission, 'message', None)
) def check_object_permissions(self, request, obj):
"""
Check if the request should be permitted for a given object.
Raises an appropriate exception if the request is not permitted.
"""
for permission in self.get_permissions():
if not permission.has_object_permission(request, self, obj):
self.permission_denied(
request, message=getattr(permission, 'message', None)
) def check_throttles(self, request):
"""
Check if request should be throttled.
Raises an appropriate exception if the request is throttled.
"""
for throttle in self.get_throttles():
if not throttle.allow_request(request, self):
self.throttled(request, throttle.wait()) def determine_version(self, request, *args, **kwargs):
"""
If versioning is being used, then determine any API version for the
incoming request. Returns a two-tuple of (version, versioning_scheme)
"""
if self.versioning_class is None:
return (None, None)
scheme = self.versioning_class()
return (scheme.determine_version(request, *args, **kwargs), scheme) # Dispatch methods def initialize_request(self, request, *args, **kwargs):
"""
Returns the initial request object.
"""
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
) def initial(self, request, *args, **kwargs):
"""
Runs anything that needs to occur prior to calling the method handler.
"""
self.format_kwarg = self.get_format_suffix(**kwargs) # Perform content negotiation and store the accepted info on the request
neg = self.perform_content_negotiation(request)
request.accepted_renderer, request.accepted_media_type = neg # Determine the API version, if versioning is in use.
version, scheme = self.determine_version(request, *args, **kwargs)
request.version, request.versioning_scheme = version, scheme # Ensure that the incoming request is permitted
self.perform_authentication(request)
self.check_permissions(request)
self.check_throttles(request) def finalize_response(self, request, response, *args, **kwargs):
"""
Returns the final response object.
"""
# Make the error obvious if a proper response is not returned
assert isinstance(response, HttpResponseBase), (
'Expected a `Response`, `HttpResponse` or `HttpStreamingResponse` '
'to be returned from the view, but received a `%s`'
% type(response)
) if isinstance(response, Response):
if not getattr(request, 'accepted_renderer', None):
neg = self.perform_content_negotiation(request, force=True)
request.accepted_renderer, request.accepted_media_type = neg response.accepted_renderer = request.accepted_renderer
response.accepted_media_type = request.accepted_media_type
response.renderer_context = self.get_renderer_context() # Add new vary headers to the response instead of overwriting.
vary_headers = self.headers.pop('Vary', None)
if vary_headers is not None:
patch_vary_headers(response, cc_delim_re.split(vary_headers)) for key, value in self.headers.items():
response[key] = value return response def handle_exception(self, exc):
"""
Handle any exception that occurs, by returning an appropriate response,
or re-raising the error.
"""
if isinstance(exc, (exceptions.NotAuthenticated,
exceptions.AuthenticationFailed)):
# WWW-Authenticate header for 401 responses, else coerce to 403
auth_header = self.get_authenticate_header(self.request) if auth_header:
exc.auth_header = auth_header
else:
exc.status_code = status.HTTP_403_FORBIDDEN exception_handler = self.get_exception_handler() context = self.get_exception_handler_context()
response = exception_handler(exc, context) if response is None:
self.raise_uncaught_exception(exc) response.exception = True
return response def raise_uncaught_exception(self, exc):
if settings.DEBUG:
request = self.request
renderer_format = getattr(request.accepted_renderer, 'format')
use_plaintext_traceback = renderer_format not in ('html', 'api', 'admin')
request.force_plaintext_errors(use_plaintext_traceback)
raise # Note: Views are made CSRF exempt from within `as_view` as to prevent
# accidental removal of this exemption in cases where `dispatch` needs to
# be overridden.
def dispatch(self, request, *args, **kwargs):
"""
`.dispatch()` is pretty much the same as Django's regular dispatch,
but with extra hooks for startup, finalize, and exception handling.
"""
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 def options(self, request, *args, **kwargs):
"""
Handler method for HTTP 'OPTIONS' request.
"""
if self.metadata_class is None:
return self.http_method_not_allowed(request, *args, **kwargs)
data = self.metadata_class().determine_metadata(request, self)
return Response(data, status=status.HTTP_200_OK)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
class APIView(View):
    def dispatch(self, request, *args, **kwargs):
        """
        `.dispatch()` is pretty much the same as Django's regular dispatch,
        but with extra hooks for startup, finalize, and exception handling.
        """
        self.args = args
        self.kwargs = kwargs
        # 第一步:对request进行加工(添加数据)
        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
            # 第三步、执行:get/post/put/delete函数
            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

下面将对dispatch完成的功能进行详细的分析

Django 的 CBV&FBV的更多相关文章

  1. Django 之 CBV & FBV

    FBV FBV(function base views) 就是在视图里使用函数处理请求. 在之前django随笔中,一直使用的是这种方式,不再赘述. CBV CBV(class base views) ...

  2. Django之CBV\FBV

    FBV(function base views) 就是在视图里使用函数处理请求. 写一个FBV的实例:在views中代码 :就是写了个函数 def book(request): ''' :param ...

  3. Python/Django(CBV/FBV/ORM操作)

    Python/Django(CBV/FBV/ORM操作) CBV:url对应的类(模式) ##====================================CBV操作============ ...

  4. django中的FBV和CBV

    django中请求处理方式有2种:FBV 和 CBV 一.FBV FBV(function base views) 就是在视图里使用函数处理请求. 看代码: urls.py from django.c ...

  5. Django的CBV与FBV

    FBV FBV(function base views) 就是在视图里使用函数处理请求. 在之前django的学习中,我们一直使用的是这种方式,所以不再赘述. CBV CBV(class base v ...

  6. Django的 CBV和FBV

    FBV CBV 回顾多重继承和Mixin 回到顶部 FBV FBV(function base views) 就是在视图里使用函数处理请求. 在之前django的学习中,我们一直使用的是这种方式,所以 ...

  7. Django之CBV和FBV

    Django之CBV和FBV CBV和FBV是C和F的区别: C是Class,F是Function 在请求中,有GET请求和POST请求. 在写CBV时,url是可以对应一个类的,在类中,分别写出GE ...

  8. django补充CBV和FBV模式

    django补充CBV和FBV模式FBV模式---函数:经常用的方式CBV模式---类CBV中url连接时函数名后面要接.as_view()class index(views.View): @... ...

  9. Django之 CBV和FBV

    FBV FBV(function base views) 就是在视图里使用函数处理请求. CBV CBV(class base views) 就是在视图里使用类处理请求. Python是一个面向对象的 ...

随机推荐

  1. 【Qt开发】Win7 64位qt-windows-x86-msvc2015-5.6.0 DLL依赖库打包

    Win7 64位qt-windows-x86-msvc2015-5.6.0 DLL依赖库打包 今天开始系统的学习QT,第一个测试的问题就是在纯净的系统中如何正常运行,也就是找出QT生成的exe的依赖库 ...

  2. css实现毛玻璃效果

    css实现毛玻璃效果,效果图 1,html代码 <div class="mainHolder"> <div class="textHolder" ...

  3. python 并发编程 多进程 生产者消费者模型总结

    生产者消费者模型总结 生产者消费者模型什么时候用? 1.程序中有两类角色 一类负责生产数据(生产者) 一类负责处理数据(消费者) 2.引入生产者消费者模型为了解决的问题是 平衡生产者与消费者之间的速度 ...

  4. windows如何使用bat快速安装计划任务?

    关键词:windows定时任务,schtasks,at ,bat schtasks 部分转自: https://www.cnblogs.com/yumianhu/p/3710743.html at的详 ...

  5. http请求跨域问题分析

    http请求跨域问题分析 个人认为可能涉及很多http的知识,本人才疏学浅不敢妄自揣测,只是做个笔记为了以后对比理解,从原生fetch说起吧,前提假设有个后端服务,我用express来模拟,如下: v ...

  6. <<C++ Primer>> 第 5 章 语句

    术语表 第 5 章 语句 块(block): 包围在花括号内的由 0 条或多条语句组成的序列.块也是一条语句,所以只要是能使用语句的地方,就可以使用块.    break语句(break statem ...

  7. C++中类模板的概念和意义

    1,在 C++ 中是否能够将泛型的思想应用于类? 1,函数模板是将泛型编程的思想应用于函数,就有了函数模板: 2,可以,常用的 C++ 标准库就是 C++ 中的标准模板库,C++ 中的 STL 就是将 ...

  8. __next__()

    def f1(n): m=n while True: m+=1 yield m a=f1(5) print(a.__next__()) 结果:6

  9. RabbitMQ入门教程(九):首部交换机Headers

    原文:RabbitMQ入门教程(九):首部交换机Headers 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog ...

  10. sql server 函数详解(3)数据类型转换函数和文本图像函数

    数据类型转换函数 文本和图像函数 --在同时处理不同数据类型的值时,SQL Server一般会自动进行隐士类型转换.对于数据类型相近的值是有效的,比如int和float,但是对于其它数据类型,例如整型 ...