美文网首页
Django 学习笔记

Django 学习笔记

作者: 米不开朗基罗 | 来源:发表于2022-09-28 09:23 被阅读0次

    [TOC]

    学习路径

    1. 序列化

    1. 对象处理
    snippet = Snippet(code='foo = "bar"\n')
    snippet.save()
    
    snippet = Snippet(code='print "hello, world"\n')
    snippet.save()
    
    1. 实例序列化
    serializer = SnippetSerializer(snippet)
    serializer.data
    # {'id': 2, 'title': u'', 'code': u'print "hello, world"\n', 'linenos': False, 'language': u'python', 'style': u'friendly'}
    
    1. 转json
    content = JSONRenderer().render(serializer.data)
    content
    # '{"id": 2, "title": "", "code": "print \\"hello, world\\"\\n", "linenos": false, "language": "python", "style": "friendly"}'
    

    2. 反序列化

    stream = BytesIO(content)
    data = JSONParser().parse(stream)
    
    1. 恢复对象实例
    serializer = SnippetSerializer(data=data)
    serializer.is_valid()
    # True
    serializer.validated_data
    # OrderedDict([('title', ''), ('code', 'print "hello, world"\n'), ('linenos', False), ('language', 'python'), ('style', 'friendly')])
    serializer.save()
    # <Snippet: Snippet object>
    
    1. (可选)序列化查询结果集(querysets)而不是模型实例
    serializer = SnippetSerializer(Snippet.objects.all(), many=True)
    serializer.data
    # [OrderedDict([('id', 1), ('title', u''), ('code', u'foo = "bar"\n'), ('linenos', False), ('language', 'python'), ('style', 'friendly')]),
    OrderedDict([('id', 2), ('title', u''), ('code', u'print "hello, world"\n'), ('linenos', False), ('language', 'python'), ('style', 'friendly')]),
    OrderedDict([('id', 3), ('title', u''), ('code', u'print "hello, world"'), ('linenos', False), ('language', 'python'), ('style', 'friendly')])]
    

    3. 基于类视图CBV

    1. 继承APIView

    简单的继承APIView

    class SnippetList(APIView):
        """
        列出所有的snippets或者创建一个新的snippet。
        """
        def get(self, request, format=None):
            snippets = Snippet.objects.all()
            serializer = SnippetSerializer(snippets, many=True)
            return Response(serializer.data)
    
        def post(self, request, format=None):
            serializer = SnippetSerializer(data=request.data)
            if serializer.is_valid():
                serializer.save()
                return Response(serializer.data, status=status.HTTP_201_CREATED)
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
    
    1. 使用混合

      继承 mixins.UpdateModelMixin|DestroyModelMixingenerics.GenericaAPIView

      class SnippetDetail(mixins.RetrieveModelMixin,
                          mixins.UpdateModelMixin,
                          mixins.DestroyModelMixin,
                          generics.GenericAPIView):
          queryset = Snippet.objects.all()
          serializer_class = SnippetSerializer
      
          def get(self, request, *args, **kwargs):
              return self.retrieve(request, *args, **kwargs)
      
          def put(self, request, *args, **kwargs):
              return self.update(request, *args, **kwargs)
      
          def delete(self, request, *args, **kwargs):
              return self.destroy(request, *args, **kwargs)
      
    1. 通用的基于类的视图

      更换 genericView → generics.RetrieveUpdateDestroyAPIView

      from snippets.models import Snippet
      from snippets.serializers import SnippetSerializer
      from rest_framework import generics
      
      class SnippetList(generics.ListCreateAPIView):
          queryset = Snippet.objects.all()
          serializer_class = SnippetSerializer
      
      class SnippetDetail(generics.RetrieveUpdateDestroyAPIView):
          queryset = Snippet.objects.all()
          serializer_class = SnippetSerializer
      

    4. 认证和权限

    前提条件:

    • 代码片段始终与创建者相关联。
    • 只有通过身份验证的用户可以创建片段。
    • 只有代码片段的创建者可以更新或删除它。
    • 未经身份验证的请求应具有完全只读访问权限。

    操作步骤:

    1. model添加 ownerhighlighted 字段

    2. model中增加 .save() 方法

    3. 为用户模型增加路径

      1. serializers.py 中追加

      2. 添加基于类的通用视图

      3. 添加urls.py

        url(r'^users/$', views.UserList.as_view()),
        url(r'^users/(?P<pk>[0-9]+)/$', views.UserDetail.as_view()),
        
    4. 将snippet和用户关联

      • snippeList 追加 perform_create 方法
      • 更新序列化器
    5. 添加视图所需权限

    6. 给Browsable API添加登录

    7. 对象级别权限控制

      • 新增permissions.py
    8. 使用API 进行身份验证

    5. 视图集ViewSets和路由器

    前言:

    • ViewSet类与View类几乎相同,不同之处在于它们提供诸如readupdate之类的操作,而不是getput等方法处理程序。

    • 最后一个ViewSet类只绑定到一组方法处理程序,当它被实例化成一组视图的时候,通常通过使用一个Router类来处理自己定义URL conf的复杂性。

    1. 使用ViewSets重构

    2. 将viewSets 绑定到url

      • 显示

        from snippets.views import SnippetViewSet, UserViewSet, api_root
        from rest_framework import renderers
        
        snippet_list = SnippetViewSet.as_view({
            'get': 'list',
            'post': 'create'
        })
        snippet_detail = SnippetViewSet.as_view({
            'get': 'retrieve',
            'put': 'update',
            'patch': 'partial_update',
            'delete': 'destroy'
        })
        snippet_highlight = SnippetViewSet.as_view({
            'get': 'highlight'
        }, renderer_classes=[renderers.StaticHTMLRenderer])
        user_list = UserViewSet.as_view({
            'get': 'list'
        })
        user_detail = UserViewSet.as_view({
            'get': 'retrieve'
        })
        
      • 具体视图

        urlpatterns = format_suffix_patterns([
            url(r'^$', api_root),
            url(r'^snippets/$', snippet_list, name='snippet-list'),
            url(r'^snippets/(?P<pk>[0-9]+)/$', snippet_detail, name='snippet-detail'),
            url(r'^snippets/(?P<pk>[0-9]+)/highlight/$', snippet_highlight, name='snippet-highlight'),
            url(r'^users/$', user_list, name='user-list'),
            url(r'^users/(?P<pk>[0-9]+)/$', user_detail, name='user-detail')
        ])
        
      • 使用路由器

        # 创建路由器并注册我们的视图。
        router = DefaultRouter()
        router.register(r'snippets', views.SnippetViewSet)
        router.register(r'users', views.UserViewSet)
        
        # API URL现在由路由器自动确定。
        # 另外,我们还要包含可浏览的API的登录URL。
        urlpatterns = [
            url(r'^', include(router.urls)),
            url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework'))
        ]
        

    5.1 视图(views)vs视图集(viewsets)之间的权衡

    使用视图集可以是一个非常有用的抽象。它有助于确保URL约定在你的API中保持一致,最大限度地减少编写所需的代码量,让你能够专注于API提供的交互和表示,而不是URLconf的细节。

    这并不意味着采用视图集总是正确的方法。在使用基于类的视图而不是基于函数的视图时,有一个类似的权衡要考虑。使用视图集不像单独构建视图那样明确。

    6. 概要和客户端库

    • 概要: 机器可读文档、描述可用api路径 ,其urls以及 支持的操作
    • 概要: 自动生成文档的有用工具,也可以用于驱动可以与api进行交互的动态客户端库

    6.1 Core API

    为了提供概要支持REST框架使用Core API

    Core API是用于描述API的文档规范。它用于提供可用路径的内部表示形式和API公开的可能的交互。它可以用于服务器端或客户端。

    6.2 添加概要

    REST框架支持明确定义的概要视图或自动生成的概要。由于我们使用的是视图集和路由器,我们可以简单地使用自动概要生成。

    你需要安装coreapi python包才能包含API概要。

    $ pip install coreapi
    

    现在我们可以通过在URL配置中包含一个自动生成的概要视图来为API添加概要。

    from rest_framework.schemas import get_schema_view
    
    schema_view = get_schema_view(title='Pastebin API')
    
    urlpatterns = [
        url('^schema/$', schema_view),
        ...
    ]
    

    如果你在浏览器中访问API根路径,那么你现在应该可以看到corejson表示形式是一个可用选项。

    6.3 使用命令行客户端

    现在我们的API暴露了一个概要路径,我们可以使用一个动态的客户端库与API进行交互。为了演示这个,我们来使用Core API命令行客户端。

    命令行客户端作为一个coreapi-cli包提供:

    $ pip install coreapi-cli
    

    现在检查它在命令行上是否可用...

    $ coreapi
    Usage: coreapi [OPTIONS] COMMAND [ARGS]...
    
      Command line client for interacting with CoreAPI services.
    
      Visit http://www.coreapi.org for more information.
    
    Options:
      --version  Display the package version number.
      --help     Show this message and exit.
    
    Commands:
    ...
    

    首先,我们将使用命令行客户端加载API概要。

    $ coreapi get http://127.0.0.1:8000/schema/
    <Pastebin API "http://127.0.0.1:8000/schema/">
        snippets: {
            highlight(id)
            list()
            read(id)
        }
        users: {
            list()
            read(id)
        }
    

    我们还没有认证,所以现在我们只能看到只读路径,这与我们设置的API权限是一致的。

    6.4 验证我们的客户端

    如果我们想要创建,编辑和删除代码片段,我们需要进行有效性用户身份验证。在这种情况下,我们只需使用基本的auth。

    请确保使用实际的用户名和密码替换下面的<username><password>

    $ coreapi credentials add 127.0.0.1 <username>:<password> --auth basic
    Added credentials
    127.0.0.1 "Basic <...>"
    

    现在,如果我们再次提取概要,我们应该能够看到一组可用的交互。

    $ coreapi reload
    

    相关文章

      网友评论

          本文标题:Django 学习笔记

          本文链接:https://www.haomeiwen.com/subject/kzxcartx.html