Django REST Framework剖析

一、简介

Django REST Framework(简称DRF),是一个用于构建Web API的强大且灵活的工具包。

先说说REST:REST是一种Web API设计标准,是目前比较成熟的一套互联网应用程序的API设计理论。

Fielding将他对互联网软件的架构原则,定名为REST,即Representational State Transfer的缩写。我对这个词组的翻译是”表现层状态转化”。如果一个架构符合REST原则,就称它为RESTful架构。所以简单来说,RESTful是一种Web API设计规范,根据产品需求需要定出一份方便前后端的规范,因此不是所有的标准要求都需要遵循。

二、Django 的 CBV&FBV

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 m 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)

APIView类源代码

?


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完成的功能进行详细的分析

原文地址:https://www.cnblogs.com/honey-badger/p/9728788.html

时间: 2024-11-04 17:41:40

Django REST Framework剖析的相关文章

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

一.简介 在上一篇博客中已经介绍了django rest framework 对于认证的源码流程,以及实现过程,当用户经过认证之后下一步就是涉及到权限的问题.比如订单的业务只能VIP才能查看,所以这时候需要对权限进行控制.下面将介绍DRF的权限控制源码剖析. 二.基本使用 这里继续使用之前的示例,加入相应的权限,这里先介绍使用示例,然后在分析权限源码 1.在django 项目下新建立目录utils,并建立permissions.py,添加权限控制: class MyPremission(obje

Django Rest Framework源码剖析(三)-----频率控制

一.简介 承接上篇文章Django Rest Framework源码剖析(二)-----权限,当服务的接口被频繁调用,导致资源紧张怎么办呢?当然或许有很多解决办法,比如:负载均衡.提高服务器配置.通过代理限制访问频率等,但是django rest framework自身就提供了访问频率的控制,可以从代码本身做控制. 二.频率控制内部原理概述 django rest framework 中频率控制基本原理基于访问次数和时间,通过计算实现,当然我们也可以自己定义频率控制方法.基本原理如下: 启用频率

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

一.简介 django rest framework 给我们带来了很多组件,除了认证.权限.序列化...其中一个重要组件就是视图,一般视图是和路由配合使用,这种方式给我们提供了更灵活的使用方法,对于使用者而言不同的视图具有不同的功能,这样我们可以根据需求定制自己视图.以下是官网传送门:http://www.django-rest-framework.org/api-guide/views/ 在之前的文章中,由于参杂了权限.认证等(如果不了解请看博客的以前的文章),但在本章中基本可以不使用,所进使

源码剖析Django REST framework的认证方式及自定义认证

源码剖析Django REST framework的认证方式 由Django的CBV模式流程,可以知道在url匹配完成后,会执行自定义的类中的as_view方法. 如果自定义的类中没有定义as_view方法,根据面向对象中类的继承可以知道,则会执行其父类View中的as_view方法 在Django的View的as_view方法中,又会调用dispatch方法. 现在来看看Django restframework的认证流程 Django restframework是基于Django的框架,所以基

Django rest framework源码分析(一) 认证

一.基础 最近正好有机会去写一些可视化的东西,就想着前后端分离,想使用django rest framework写一些,顺便复习一下django rest framework的知识,只是顺便哦,好吧.我承认我是故意的,因为我始终觉得,如果好的技术服务于企业,顺便的提高一下自己.大家都很开心不是不.再次强调一下,真的只是顺便. 安装吧 pip install djangorestframework 1.2.需要先了解的一些知识 理解下面两个知识点非常重要,django-rest-framework

利用 Django REST framework 编写 RESTful API

利用 Django REST framework 编写 RESTful API Updateat 2015/12/3: 增加 filter 最近在玩 Django,不得不说 rest_framework 真乃一大神器,可以轻易的甚至自动化的搞定很多事情,比如: 自动生成符合 RESTful 规范的 API 支持 OPTION.HEAD.POST.GET.PATCH.PUT.DELETE 根据 Content-Type 来动态的返回数据类型(如 text.json) 生成 browserable

django rest framework 入门

django rest framework 入门1-序列化 Serialization 分类: Python 2013-01-22 22:24 11528人阅读 评论(0) 收藏 举报 djangopythonrest framework ************************************ 广告时间: 海淘导航网站推荐:海淘库:http://www.haitaocool.com/ 需要的请收藏哦 ************************************ 1.

Django rest framework 使用自定义认证方式

Django rest framework 使用自定义认证方式 Django使用自定义认证方式 介绍了 "Django使用自定义认证方式",这一篇说说怎样在前一篇的基础上提供rest api. 修改settings.py中INSTALLED_APPS,添加 'login' app. 给login app增加serializers.py文件 #coding:utf-8 from django.contrib.auth.models import User from rest_framew

Django REST framework 的TokenAuth认证及外键Serializer基本实现

一,Models.py中,ForeignKey记得要有related_name属性,已实现关联对象反向引用. app_name = models.ForeignKey("cmdb.App",related_name='deploy_app', verbose_name="App") 二,Settings.py文件中,加入对Django REST framework的基本设置. REST_FRAMEWORK = { 'DEFAULT_PERMISSION_CLASSE