Django 的 CBV&FBV

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

url

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

views

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

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

url

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

views

  1. from django.shortcuts import HttpResponse
  2. from django.views import View
  3.  
  4. class StudentsView(View):
  5.  
  6. def get(self,request,*args,**kwargs):
  7. return HttpResponse('GET')
  8.  
  9. def post(self, request, *args, **kwargs):
  10. return HttpResponse('POST')
  11.  
  12. def put(self, request, *args, **kwargs):
  13. return HttpResponse('PUT')
  14.  
  15. def delete(self, request, *args, **kwargs):
  16. 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. class View(object):
  2. """
  3. Intentionally simple parent class for all views. Only implements
  4. dispatch-by-method and simple sanity checking.
  5. """
  6.  
  7. http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']
  8.  
  9. def __init__(self, **kwargs):
  10. """
  11. Constructor. Called in the URLconf; can contain helpful extra
  12. keyword arguments, and other things.
  13. """
  14. # Go through keyword arguments, and either save their values to our
  15. # instance, or raise an error.
  16. for key, value in six.iteritems(kwargs):
  17. setattr(self, key, value)
  18.  
  19. @classonlymethod
  20. def as_view(cls, **initkwargs):
  21. """
  22. Main entry point for a request-response process.
  23. """
  24. for key in initkwargs:
  25. if key in cls.http_method_names:
  26. raise TypeError("You tried to pass in the %s method name as a "
  27. "keyword argument to %s(). Don't do that."
  28. % (key, cls.__name__))
  29. if not hasattr(cls, key):
  30. raise TypeError("%s() received an invalid keyword %r. as_view "
  31. "only accepts arguments that are already "
  32. "attributes of the class." % (cls.__name__, key))
  33.  
  34. def view(request, *args, **kwargs):
  35. self = cls(**initkwargs)
  36. if hasattr(self, 'get') and not hasattr(self, 'head'):
  37. self.head = self.get
  38. self.request = request
  39. self.args = args
  40. self.kwargs = kwargs
  41. return self.dispatch(request, *args, **kwargs)
  42. view.view_class = cls
  43. view.view_initkwargs = initkwargs
  44.  
  45. # take name and docstring from class
  46. update_wrapper(view, cls, updated=())
  47.  
  48. # and possible attributes set by decorators
  49. # like csrf_exempt from dispatch
  50. update_wrapper(view, cls.dispatch, assigned=())
  51. return view
  52.  
  53. def dispatch(self, request, *args, **kwargs):
  54. # Try to dispatch to the right method; if a method doesn't exist,
  55. # defer to the error handler. Also defer to the error handler if the
  56. # request method isn't on the approved list.
  57. if request.method.lower() in self.http_method_names:
  58. handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
  59. else:
  60. handler = self.http_method_not_allowed
  61. return handler(request, *args, **kwargs)
  62.  
  63. def http_method_not_allowed(self, request, *args, **kwargs):
  64. logger.warning(
  65. 'Method Not Allowed (%s): %s', request.method, request.path,
  66. extra={'status_code': 405, 'request': request}
  67. )
  68. return http.HttpResponseNotAllowed(self._allowed_methods())
  69.  
  70. def options(self, request, *args, **kwargs):
  71. """
  72. Handles responding to requests for the OPTIONS HTTP verb.
  73. """
  74. response = http.HttpResponse()
  75. response['Allow'] = ', '.join(self._allowed_methods())
  76. response['Content-Length'] = '0'
  77. return response
  78.  
  79. def _allowed_methods(self):
  80. return [m.upper() for m in self.http_method_names if hasattr(self, m)]

View类里面的部分如下:

  1. @classonlymethod
  2. def as_view(cls, **initkwargs):
  3. """
  4. Main entry point for a request-response process.
  5. """
  6. for key in initkwargs:
  7. if key in cls.http_method_names:
  8. raise TypeError("You tried to pass in the %s method name as a "
  9. "keyword argument to %s(). Don't do that."
  10. % (key, cls.__name__))
  11. if not hasattr(cls, key):
  12. raise TypeError("%s() received an invalid keyword %r. as_view "
  13. "only accepts arguments that are already "
  14. "attributes of the class." % (cls.__name__, key))
  15.  
  16. def view(request, *args, **kwargs):
  17. self = cls(**initkwargs)
  18. if hasattr(self, 'get') and not hasattr(self, 'head'):
  19. self.head = self.get
  20. self.request = request
  21. self.args = args
  22. self.kwargs = kwargs
  23. return self.dispatch(request, *args, **kwargs)
  24. view.view_class = cls
  25. view.view_initkwargs = initkwargs
  26.  
  27. # take name and docstring from class
  28. update_wrapper(view, cls, updated=())
  29.  
  30. # and possible attributes set by decorators
  31. # like csrf_exempt from dispatch
  32. update_wrapper(view, cls.dispatch, assigned=())
  33. 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. def dispatch(self, request, *args, **kwargs):
  2. # Try to dispatch to the right method; if a method doesn't exist,
  3. # defer to the error handler. Also defer to the error handler if the
  4. # request method isn't on the approved list.
  5. if request.method.lower() in self.http_method_names:
  6. handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
  7. else:
  8. handler = self.http_method_not_allowed
  9. 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. from rest_framework.views import APIView
  2. from django.shortcuts import HttpResponse
  3.  
  4. class StudentsView(APIView):
  5.  
  6. def get(self, request, *args, **kwargs):
  7. return HttpResponse('GET')
  8.  
  9. def post(self, request, *args, **kwargs):
  10. return HttpResponse('POST')
  11.  
  12. def put(self, request, *args, **kwargs):
  13. return HttpResponse('PUT')
  14.  
  15. def delete(self, request, *args, **kwargs):
  16. 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方法有很多的功能

  1. class APIView(View):
  2.  
  3. # The following policies may be set at either globally, or per-view.
  4. renderer_classes = api_settings.DEFAULT_RENDERER_CLASSES
  5. parser_classes = api_settings.DEFAULT_PARSER_CLASSES
  6. authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES
  7. throttle_classes = api_settings.DEFAULT_THROTTLE_CLASSES
  8. permission_classes = api_settings.DEFAULT_PERMISSION_CLASSES
  9. content_negotiation_class = api_settings.DEFAULT_CONTENT_NEGOTIATION_CLASS
  10. metadata_class = api_settings.DEFAULT_METADATA_CLASS
  11. versioning_class = api_settings.DEFAULT_VERSIONING_CLASS
  12.  
  13. # Allow dependency injection of other settings to make testing easier.
  14. settings = api_settings
  15.  
  16. schema = DefaultSchema()
  17.  
  18. @classmethod
  19. def as_view(cls, **initkwargs):
  20. """
  21. Store the original class on the view function.
  22.  
  23. This allows us to discover information about the view when we do URL
  24. reverse lookups. Used for breadcrumb generation.
  25. """
  26. if isinstance(getattr(cls, 'queryset', None), models.query.QuerySet):
  27. def force_evaluation():
  28. raise RuntimeError(
  29. 'Do not evaluate the `.queryset` attribute directly, '
  30. 'as the result will be cached and reused between requests. '
  31. 'Use `.all()` or call `.get_queryset()` instead.'
  32. )
  33. cls.queryset._fetch_all = force_evaluation
  34.  
  35. view = super(APIView, cls).as_view(**initkwargs)
  36. view.cls = cls
  37. view.initkwargs = initkwargs
  38.  
  39. # Note: session based authentication is explicitly CSRF validated,
  40. # all other authentication is CSRF exempt.
  41. return csrf_exempt(view)
  42.  
  43. @property
  44. def allowed_methods(self):
  45. """
  46. Wrap Django's private `_allowed_methods` interface in a public property.
  47. """
  48. return self._allowed_methods()
  49.  
  50. @property
  51. def default_response_headers(self):
  52. headers = {
  53. 'Allow': ', '.join(self.allowed_methods),
  54. }
  55. if len(self.renderer_classes) > 1:
  56. headers['Vary'] = 'Accept'
  57. return headers
  58.  
  59. def http_method_not_allowed(self, request, *args, **kwargs):
  60. """
  61. If `request.method` does not correspond to a handler method,
  62. determine what kind of exception to raise.
  63. """
  64. raise exceptions.MethodNotAllowed(request.method)
  65.  
  66. def permission_denied(self, request, message=None):
  67. """
  68. If request is not permitted, determine what kind of exception to raise.
  69. """
  70. if request.authenticators and not request.successful_authenticator:
  71. raise exceptions.NotAuthenticated()
  72. raise exceptions.PermissionDenied(detail=message)
  73.  
  74. def throttled(self, request, wait):
  75. """
  76. If request is throttled, determine what kind of exception to raise.
  77. """
  78. raise exceptions.Throttled(wait)
  79.  
  80. def get_authenticate_header(self, request):
  81. """
  82. If a request is unauthenticated, determine the WWW-Authenticate
  83. header to use for 401 responses, if any.
  84. """
  85. authenticators = self.get_authenticators()
  86. if authenticators:
  87. return authenticators[0].authenticate_header(request)
  88.  
  89. def get_parser_context(self, http_request):
  90. """
  91. Returns a dict that is passed through to Parser.parse(),
  92. as the `parser_context` keyword argument.
  93. """
  94. # Note: Additionally `request` and `encoding` will also be added
  95. # to the context by the Request object.
  96. return {
  97. 'view': self,
  98. 'args': getattr(self, 'args', ()),
  99. 'kwargs': getattr(self, 'kwargs', {})
  100. }
  101.  
  102. def get_renderer_context(self):
  103. """
  104. Returns a dict that is passed through to Renderer.render(),
  105. as the `renderer_context` keyword argument.
  106. """
  107. # Note: Additionally 'response' will also be added to the context,
  108. # by the Response object.
  109. return {
  110. 'view': self,
  111. 'args': getattr(self, 'args', ()),
  112. 'kwargs': getattr(self, 'kwargs', {}),
  113. 'request': getattr(self, 'request', None)
  114. }
  115.  
  116. def get_exception_handler_context(self):
  117. """
  118. Returns a dict that is passed through to EXCEPTION_HANDLER,
  119. as the `context` argument.
  120. """
  121. return {
  122. 'view': self,
  123. 'args': getattr(self, 'args', ()),
  124. 'kwargs': getattr(self, 'kwargs', {}),
  125. 'request': getattr(self, 'request', None)
  126. }
  127.  
  128. def get_view_name(self):
  129. """
  130. Return the view name, as used in OPTIONS responses and in the
  131. browsable API.
  132. """
  133. func = self.settings.VIEW_NAME_FUNCTION
  134. return func(self.__class__, getattr(self, 'suffix', None))
  135.  
  136. def get_view_description(self, html=False):
  137. """
  138. Return some descriptive text for the view, as used in OPTIONS responses
  139. and in the browsable API.
  140. """
  141. func = self.settings.VIEW_DESCRIPTION_FUNCTION
  142. return func(self.__class__, html)
  143.  
  144. # API policy instantiation methods
  145.  
  146. def get_format_suffix(self, **kwargs):
  147. """
  148. Determine if the request includes a '.json' style format suffix
  149. """
  150. if self.settings.FORMAT_SUFFIX_KWARG:
  151. return kwargs.get(self.settings.FORMAT_SUFFIX_KWARG)
  152.  
  153. def get_renderers(self):
  154. """
  155. Instantiates and returns the list of renderers that this view can use.
  156. """
  157. return [renderer() for renderer in self.renderer_classes]
  158.  
  159. def get_parsers(self):
  160. """
  161. Instantiates and returns the list of parsers that this view can use.
  162. """
  163. return [parser() for parser in self.parser_classes]
  164.  
  165. def get_authenticators(self):
  166. """
  167. Instantiates and returns the list of authenticators that this view can use.
  168. """
  169. return [auth() for auth in self.authentication_classes]
  170.  
  171. def get_permissions(self):
  172. """
  173. Instantiates and returns the list of permissions that this view requires.
  174. """
  175. return [permission() for permission in self.permission_classes]
  176.  
  177. def get_throttles(self):
  178. """
  179. Instantiates and returns the list of throttles that this view uses.
  180. """
  181. return [throttle() for throttle in self.throttle_classes]
  182.  
  183. def get_content_negotiator(self):
  184. """
  185. Instantiate and return the content negotiation class to use.
  186. """
  187. if not getattr(self, '_negotiator', None):
  188. self._negotiator = self.content_negotiation_class()
  189. return self._negotiator
  190.  
  191. def get_exception_handler(self):
  192. """
  193. Returns the exception handler that this view uses.
  194. """
  195. return self.settings.EXCEPTION_HANDLER
  196.  
  197. # API policy implementation methods
  198.  
  199. def perform_content_negotiation(self, request, force=False):
  200. """
  201. Determine which renderer and media type to use render the response.
  202. """
  203. renderers = self.get_renderers()
  204. conneg = self.get_content_negotiator()
  205.  
  206. try:
  207. return conneg.select_renderer(request, renderers, self.format_kwarg)
  208. except Exception:
  209. if force:
  210. return (renderers[0], renderers[0].media_type)
  211. raise
  212.  
  213. def perform_authentication(self, request):
  214. """
  215. Perform authentication on the incoming request.
  216.  
  217. Note that if you override this and simply 'pass', then authentication
  218. will instead be performed lazily, the first time either
  219. `request.user` or `request.auth` is accessed.
  220. """
  221. request.user
  222.  
  223. def check_permissions(self, request):
  224. """
  225. Check if the request should be permitted.
  226. Raises an appropriate exception if the request is not permitted.
  227. """
  228. for permission in self.get_permissions():
  229. if not permission.has_permission(request, self):
  230. self.permission_denied(
  231. request, message=getattr(permission, 'message', None)
  232. )
  233.  
  234. def check_object_permissions(self, request, obj):
  235. """
  236. Check if the request should be permitted for a given object.
  237. Raises an appropriate exception if the request is not permitted.
  238. """
  239. for permission in self.get_permissions():
  240. if not permission.has_object_permission(request, self, obj):
  241. self.permission_denied(
  242. request, message=getattr(permission, 'message', None)
  243. )
  244.  
  245. def check_throttles(self, request):
  246. """
  247. Check if request should be throttled.
  248. Raises an appropriate exception if the request is throttled.
  249. """
  250. for throttle in self.get_throttles():
  251. if not throttle.allow_request(request, self):
  252. self.throttled(request, throttle.wait())
  253.  
  254. def determine_version(self, request, *args, **kwargs):
  255. """
  256. If versioning is being used, then determine any API version for the
  257. incoming request. Returns a two-tuple of (version, versioning_scheme)
  258. """
  259. if self.versioning_class is None:
  260. return (None, None)
  261. scheme = self.versioning_class()
  262. return (scheme.determine_version(request, *args, **kwargs), scheme)
  263.  
  264. # Dispatch methods
  265.  
  266. def initialize_request(self, request, *args, **kwargs):
  267. """
  268. Returns the initial request object.
  269. """
  270. parser_context = self.get_parser_context(request)
  271.  
  272. return Request(
  273. request,
  274. parsers=self.get_parsers(),
  275. authenticators=self.get_authenticators(),
  276. negotiator=self.get_content_negotiator(),
  277. parser_context=parser_context
  278. )
  279.  
  280. def initial(self, request, *args, **kwargs):
  281. """
  282. Runs anything that needs to occur prior to calling the method handler.
  283. """
  284. self.format_kwarg = self.get_format_suffix(**kwargs)
  285.  
  286. # Perform content negotiation and store the accepted info on the request
  287. neg = self.perform_content_negotiation(request)
  288. request.accepted_renderer, request.accepted_media_type = neg
  289.  
  290. # Determine the API version, if versioning is in use.
  291. version, scheme = self.determine_version(request, *args, **kwargs)
  292. request.version, request.versioning_scheme = version, scheme
  293.  
  294. # Ensure that the incoming request is permitted
  295. self.perform_authentication(request)
  296. self.check_permissions(request)
  297. self.check_throttles(request)
  298.  
  299. def finalize_response(self, request, response, *args, **kwargs):
  300. """
  301. Returns the final response object.
  302. """
  303. # Make the error obvious if a proper response is not returned
  304. assert isinstance(response, HttpResponseBase), (
  305. 'Expected a `Response`, `HttpResponse` or `HttpStreamingResponse` '
  306. 'to be returned from the view, but received a `%s`'
  307. % type(response)
  308. )
  309.  
  310. if isinstance(response, Response):
  311. if not getattr(request, 'accepted_renderer', None):
  312. neg = self.perform_content_negotiation(request, force=True)
  313. request.accepted_renderer, request.accepted_media_type = neg
  314.  
  315. response.accepted_renderer = request.accepted_renderer
  316. response.accepted_media_type = request.accepted_media_type
  317. response.renderer_context = self.get_renderer_context()
  318.  
  319. # Add new vary headers to the response instead of overwriting.
  320. vary_headers = self.headers.pop('Vary', None)
  321. if vary_headers is not None:
  322. patch_vary_headers(response, cc_delim_re.split(vary_headers))
  323.  
  324. for key, value in self.headers.items():
  325. response[key] = value
  326.  
  327. return response
  328.  
  329. def handle_exception(self, exc):
  330. """
  331. Handle any exception that occurs, by returning an appropriate response,
  332. or re-raising the error.
  333. """
  334. if isinstance(exc, (exceptions.NotAuthenticated,
  335. exceptions.AuthenticationFailed)):
  336. # WWW-Authenticate header for 401 responses, else coerce to 403
  337. auth_header = self.get_authenticate_header(self.request)
  338.  
  339. if auth_header:
  340. exc.auth_header = auth_header
  341. else:
  342. exc.status_code = status.HTTP_403_FORBIDDEN
  343.  
  344. exception_handler = self.get_exception_handler()
  345.  
  346. context = self.get_exception_handler_context()
  347. response = exception_handler(exc, context)
  348.  
  349. if response is None:
  350. self.raise_uncaught_exception(exc)
  351.  
  352. response.exception = True
  353. return response
  354.  
  355. def raise_uncaught_exception(self, exc):
  356. if settings.DEBUG:
  357. request = self.request
  358. renderer_format = getattr(request.accepted_renderer, 'format')
  359. use_plaintext_traceback = renderer_format not in ('html', 'api', 'admin')
  360. request.force_plaintext_errors(use_plaintext_traceback)
  361. raise
  362.  
  363. # Note: Views are made CSRF exempt from within `as_view` as to prevent
  364. # accidental removal of this exemption in cases where `dispatch` needs to
  365. # be overridden.
  366. def dispatch(self, request, *args, **kwargs):
  367. """
  368. `.dispatch()` is pretty much the same as Django's regular dispatch,
  369. but with extra hooks for startup, finalize, and exception handling.
  370. """
  371. self.args = args
  372. self.kwargs = kwargs
  373. request = self.initialize_request(request, *args, **kwargs)
  374. self.request = request
  375. self.headers = self.default_response_headers # deprecate?
  376.  
  377. try:
  378. self.initial(request, *args, **kwargs)
  379.  
  380. # Get the appropriate handler method
  381. if request.method.lower() in self.http_method_names:
  382. handler = getattr(self, request.method.lower(),
  383. self.http_method_not_allowed)
  384. else:
  385. handler = self.http_method_not_allowed
  386.  
  387. response = handler(request, *args, **kwargs)
  388.  
  389. except Exception as exc:
  390. response = self.handle_exception(exc)
  391.  
  392. self.response = self.finalize_response(request, response, *args, **kwargs)
  393. return self.response
  394.  
  395. def options(self, request, *args, **kwargs):
  396. """
  397. Handler method for HTTP 'OPTIONS' request.
  398. """
  399. if self.metadata_class is None:
  400. return self.http_method_not_allowed(request, *args, **kwargs)
  401. data = self.metadata_class().determine_metadata(request, self)
  402. return Response(data, status=status.HTTP_200_OK)

APIView类源代码

  1. class APIView(View):
  2. def dispatch(self, request, *args, **kwargs):
  3. """
  4. `.dispatch()` is pretty much the same as Django's regular dispatch,
  5. but with extra hooks for startup, finalize, and exception handling.
  6. """
  7. self.args = args
  8. self.kwargs = kwargs
  9. # 第一步:对request进行加工(添加数据)
  10. request = self.initialize_request(request, *args, **kwargs)
  11. self.request = request
  12. self.headers = self.default_response_headers # deprecate?
  13.  
  14. try:
  15. # 第二步:
  16. # 处理版权信息
  17. # 认证
  18. # 权限
  19. # 请求用户进行访问频率的限制
  20. self.initial(request, *args, **kwargs)
  21.  
  22. # Get the appropriate handler method
  23. if request.method.lower() in self.http_method_names:
  24. handler = getattr(self, request.method.lower(),
  25. self.http_method_not_allowed)
  26. else:
  27. handler = self.http_method_not_allowed
  28. # 第三步、执行:get/post/put/delete函数
  29. response = handler(request, *args, **kwargs)
  30.  
  31. except Exception as exc:
  32. response = self.handle_exception(exc)
  33. # 第四步、 对返回结果再次进行加工
  34. self.response = self.finalize_response(request, response, *args, **kwargs)
  35. return self.response

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

Django REST framework 总结(附源码剖析)的更多相关文章

  1. 使用MiniProfiler给Asp.net MVC和Entity Framework号脉(附源码)

    在学习python开发框架pylons/pyramid的过程中,里面有个非常棒的页面性能监控功能,这样在开发过程中,你能清楚的知道当前页面的性能以及其它参数. 这里介绍一下如何给Asp.net MVC ...

  2. Django REST framework —— 权限组件源码分析

    在上一篇文章中我们已经分析了认证组件源码,我们再来看看权限组件的源码,权限组件相对容易,因为只需要返回True 和False即可 代码 class ShoppingCarView(ViewSetMix ...

  3. Django REST framework —— 认证组件源码分析

    我在前面的博客里已经讲过了,我们一般编写API的时候用的方式 class CoursesView(ViewSetMixin,APIView): pass 这种方式的有点是,灵活性比较大,可以根据自己的 ...

  4. Django rest framework框架——APIview源码分析

    一.什么是rest REST其实是一种组织Web服务的架构,而并不是我们想象的那样是实现Web服务的一种新的技术,更没有要求一定要使用HTTP.其目标是为了创建具有良好扩展性的分布式系统. 可用一句话 ...

  5. Django rest framework 权限操作(源码分析)

    知识回顾http://www.cnblogs.com/ctztake/p/8419059.html 这一篇是基于上一篇写的,上一篇谢了认证的具体流程,看懂了上一篇这一篇才能看懂, 当用户访问是 首先执 ...

  6. Django Rest Framework源码剖析(五)-----解析器

    一.简介 解析器顾名思义就是对请求体进行解析.为什么要有解析器?原因很简单,当后台和前端进行交互的时候数据类型不一定都是表单数据或者json,当然也有其他类型的数据格式,比如xml,所以需要解析这类数 ...

  7. Django Rest Framework源码剖析(二)-----权限

    一.简介 在上一篇博客中已经介绍了django rest framework 对于认证的源码流程,以及实现过程,当用户经过认证之后下一步就是涉及到权限的问题.比如订单的业务只能VIP才能查看,所以这时 ...

  8. Django Rest Framework源码剖析(八)-----视图与路由

    一.简介 django rest framework 给我们带来了很多组件,除了认证.权限.序列化...其中一个重要组件就是视图,一般视图是和路由配合使用,这种方式给我们提供了更灵活的使用方法,对于使 ...

  9. Django Rest Framework源码剖析(七)-----分页

    一.简介 分页对于大多数网站来说是必不可少的,那你使用restful架构时候,你可以从后台获取数据,在前端利用利用框架或自定义分页,这是一种解决方案.当然django rest framework提供 ...

随机推荐

  1. 解决react-native软键盘弹出挡住输入框的问题

    解决react-native软键盘弹出挡住输入框的问题 写登录页面,整体界面居中之后就出现软键盘弹出挡住输入框,用户体验不好的情况.用了RN官方的KeyboardAvoidingView组件,会有多出 ...

  2. GCC栈溢出保护

    逆向过elf程序都知道,GCC的canary,x86_64下从fs:0x28偏移处获取,32位下从gs:0x14偏移处获取.但知道canary如何产生,为什么在这里取的人比较少. 下面以x86_64平 ...

  3. POJ 1200:Crazy Search(哈希)

    Crazy Search Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 32483   Accepted: 8947 Des ...

  4. hdu 1864 最大报销额 01背包

    Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s) ...

  5. CodeForces 682A

    D - Alyona and Numbers Time Limit:1000MS Memory Limit:262144KB 64bit IO Format:%I64d & %I64u Sub ...

  6. django 一个关于分组查询的问题分析

    ret=Emp.objects.values('dep').annotate(avg_salary=Avg('salary')) print(ret) # ---*******单表分组查询ORM总结: ...

  7. Caused by: java.sql.SQLException: ORA-24816: 在实际的 LONG 或 LOB 列之后提供了扩展的非 LONG 绑定数据

    今天客户说报告草稿保存不了,跟踪错误bug,了解到以下reason: 异常出现的环境:oracle11g + Hibernate 错误分析:这是oracle 11g在clob字段中的一个bug,ora ...

  8. canvas 使用 isPointInPath() 判断鼠标位置是否在绘制的元素上

    canvas 里绘制的图形不是一个实体 DOM,所以要给每个绘制的图形添加事件操作比给 DOM 添加事件要复杂很多. 所以,我们需要使用一个 canvas 的 isPointInPath(x, y) ...

  9. Go Example--数组

    package main import "fmt" func main() { //定义一个数组并完成初始化,初始值为对应的零值 var a [5]int fmt.Println( ...

  10. linux 之sed

    sed 用法 sed [-nefr] [action] -i 直接修改文件内容,而不是像其他命令那样只是输出到终端 a新增c取代d删除i插入p列印常与sed -n 使用s取代 有一点需要注意的是:如果 ...