zoukankan      html  css  js  c++  java
  • [oldboy-django][2深入django]rest-framework教程

    # rest-framework教程
        - settings.py
            INSTALL-APPS = [
                'snippets',  # app
                'rest-framework',
            ]
        
        - 创建model
            # -*- coding: utf-8 -*-
            from __future__ import unicode_literals
    
            from django.db import models
            from pygments.lexers import get_all_lexers
            from pygments.styles import get_all_styles
    
            LEXERS = [item for item in get_all_lexers() if item[1]]
            LANGUAGE_CHOICES = sorted([(item[1][0], item[0]) for item in LEXERS])
            STYLE_CHOICES = sorted((item, item) for item in get_all_styles())
    
    
            class Snippet(models.Model):
                created = models.DateTimeField(auto_now_add=True)
                title = models.CharField(max_length=100, blank=True, default='')
                code = models.TextField()
                linenos = models.BooleanField(default=False)
                language = models.CharField(choices=LANGUAGE_CHOICES, default='python', max_length=100)
                style = models.CharField(choices=STYLE_CHOICES, default='friendly', max_length=100)
    
                class Meta:
                    ordering = ('created',)
        
        - 创建serializer 麻烦
    
            # -*- coding: utf-8 -*-
            from rest_framework import serializers
            from snippets.models import Snippet, LANGUAGE_CHOICES, STYLE_CHOICES
    
    
            # 不继承ModelSerializer, 自己定义create, update,这两个函数在SnippetSerializer对象.save()执行事被调用
            class SnippetSerializer(serializers.Serializer):
                id = serializers.IntegerField(read_only=True)
                title = serializers.CharField(required=False, allow_blank=True, max_length=100)
                code = serializers.CharField(style={'base_template': 'textarea.html'})
                linenos = serializers.BooleanField(required=False)
                language = serializers.ChoiceField(choices=LANGUAGE_CHOICES, default='python')
                style = serializers.ChoiceField(choices=STYLE_CHOICES, default='friendly')
    
                def create(self, validated_data):
                    """
                    Create and return a new `Snippet` instance, given the validated data.
                    """
                    return Snippet.objects.create(**validated_data)
    
                def update(self, instance, validated_data):
                    """
                    Update and return an existing `Snippet` instance, given the validated data.
                    """
                    instance.title = validated_data.get('title', instance.title)
                    instance.code = validated_data.get('code', instance.code)
                    instance.linenos = validated_data.get('linenos', instance.linenos)
                    instance.language = validated_data.get('language', instance.language)
                    instance.style = validated_data.get('style', instance.style)
                    instance.save()
                    return instance
    
        - 创建Serializer,简便
            class SnippetSerializer(serializers.ModelSerializer):
                class Meta:
                    model = Snippet
                    fields = ('id', 'title', 'code', 'linenos', 'language', 'style') 
            
            # 和上面是一样的,ModelSerializer里面定义了create,update方法
            # 不信你执行下面语句
                serializer = SnippetSerializer()
                print(repr(serializer))
            
            
        - 添加数据(添加两条数据)
            python manage.py shell
            >>>from snippets.models import Snippet
            >>> snippet = Snippet(code='foo = "bar"
    ')
            >>> snippet.save()
            >>>
            >>>
            >>> snippet = Snippet(code='print "hello, world"
    ')
            >>> snippet.save()
    
        - 使用serializer 得到dict数据 : serializer对象.data
            >>> snippet = Snippet.objects.all()[1]
            >>> serializer = SnippetSerializer(snippet)
            >>> serializer.data
            {'style': 'friendly', 'code': u'print "hello, world"
    ', 'language': 'python', 'title': u'', 'linenos': False, 'id': 2}
        
        - 使用serializer得到Json数据  --序列化
            >>> from rest_framework.renderers import JSONRenderer
            >>> snippet = Snippet.objects.all()[1]
            >>> serializer = SnippetSerializer(snippet)
            >>> content= JSONRenderer().render(serializer.data)
            >>> content
            '{"id":2,"title":"","code":"print \"hello, world\"\n","linenos":false,"language":"python","style":"friendly"}'
            >>>
    
        - 使用serializer反序列化得到字典数据
    
            >>> from rest_framework.renderers import JSONRenderer
            >>> content= JSONRenderer().render(serializer.data)
            >>> content
            '{"id":2,"title":"","code":"print \"hello, world\"\n","linenos":false,"language":"python","style":"friendly"}'
            >>> from rest_framework.parsers import JSONParser
            >>> data = JSONParser().parse(content)
                # 会报错,因为content不是句柄(可读)
                AttributeError: 'str' object has no attribute 'read'
            >>> f = open('a.data','wb')
            >>> f.write(content)
            >>> f.close()
            >>> f = open('a.data','rb')
            >>> data = JSONParser().parse(f)
            >>> data
                {u'style': u'friendly', u'code': u'print "hello, world"
    ', u'language': u'python', u'title': u'', u'linenos': False, u'id': 2}
    
        - 使用serializer插入数据  -- data为上面的data
            >>> serializer = SnippetSerializer(data=data)  # 相当于插入数据
            >>> serializer.is_valid()
            True
            >>> serializer.validated_data
            OrderedDict([(u'title', u''), (u'code', u'print "hello, world"'), (u'linenos', False), (u'language', 'python'), (u'style', 'friendly')])
            >>> serializer.save()
            <Snippet: Snippet object>
            
            # 数据库保存, 查看数据库会发现已经多了一条数据
        
        - 将多个对象序列化many=True
            >>> serializer = SnippetSerializer(Snippet.objects.all(), many=True)
            >>> serializer.data
            [OrderedDict([('id', 1), ('title', u''), ('code', u'foo = "bar"
    '), ('linenos', False), ('language', 'python'), ('style', 'friendly')]), Orde
            redDict([('id', 2), ('title', u''), ('code', u'print "hello, world"
    '), ('linenos', False), ('language', 'python'), ('style', 'friendly')]),
            OrderedDict([('id', 3), ('title', u''), ('code', u'print "hello, world"'), ('linenos', False), ('language', 'python'), ('style', 'friendly')])
            ]
    
        
        - 创建views
            -- 工程.url
                urlpatterns = [
                    url(r'^admin/', admin.site.urls),
                    url(r'^', include('snippets.urls')),
                ]
            -- snippets.url
            urlpatterns = [
                url(r'^snippets/$', views.snippet_list),
                url(r'^snippets/(?P<pk>[0-9]+)/$', views.snippet_detail),
            ]
            -- 视图函数
                # -*- coding: utf-8 -*-
                from __future__ import unicode_literals
    
                from django.shortcuts import render, HttpResponse
                from django.http import JsonResponse
                from snippets.models import Snippet
                from snippets.serializer import SnippetSerializer
    
    
                # Create your views here.
                def snippet_list(request):
                    if request.method == 'GET':
                        snippets = Snippet.objects.all()
                        serializer = SnippetSerializer(snippets, many=True)
                        return JsonResponse(serializer.data, safe=False)
    
    
                def snippet_detail(request, pk):
                    try:
                        snippet = Snippet.objects.get(pk=pk)
                    except Snippet.DoesNotExist:
                        return HttpResponse(status=404)
    
                    if request.method == 'GET':
                        serializer = SnippetSerializer(snippet)
                        return JsonResponse(serializer.data)
    
        
    View Code

     官网:http://www.django-rest-framework.org/tutorial/5-relationships-and-hyperlinked-apis/

     中文翻译比较好:http://www.cnblogs.com/zivwong/p/7461764.html

    -- serializer序列化和反序列化

    -# rest-framework教程
        - settings.py
            INSTALL-APPS = [
                'snippets',  # app
                'rest-framework',
            ]
        
        - 创建model
            # -*- coding: utf-8 -*-
            from __future__ import unicode_literals
    
            from django.db import models
            from pygments.lexers import get_all_lexers
            from pygments.styles import get_all_styles
    
            LEXERS = [item for item in get_all_lexers() if item[1]]
            LANGUAGE_CHOICES = sorted([(item[1][0], item[0]) for item in LEXERS])
            STYLE_CHOICES = sorted((item, item) for item in get_all_styles())
    
    
            class Snippet(models.Model):
                created = models.DateTimeField(auto_now_add=True)
                title = models.CharField(max_length=100, blank=True, default='')
                code = models.TextField()
                linenos = models.BooleanField(default=False)
                language = models.CharField(choices=LANGUAGE_CHOICES, default='python', max_length=100)
                style = models.CharField(choices=STYLE_CHOICES, default='friendly', max_length=100)
    
                class Meta:
                    ordering = ('created',)
        
        - 创建serializer 麻烦
    
            # -*- coding: utf-8 -*-
            from rest_framework import serializers
            from snippets.models import Snippet, LANGUAGE_CHOICES, STYLE_CHOICES
    
    
            # 不继承ModelSerializer, 自己定义create, update,这两个函数在SnippetSerializer对象.save()执行事被调用
            class SnippetSerializer(serializers.Serializer):
                id = serializers.IntegerField(read_only=True)
                title = serializers.CharField(required=False, allow_blank=True, max_length=100)
                code = serializers.CharField(style={'base_template': 'textarea.html'})
                linenos = serializers.BooleanField(required=False)
                language = serializers.ChoiceField(choices=LANGUAGE_CHOICES, default='python')
                style = serializers.ChoiceField(choices=STYLE_CHOICES, default='friendly')
    
                def create(self, validated_data):
                    """
                    Create and return a new `Snippet` instance, given the validated data.
                    """
                    return Snippet.objects.create(**validated_data)
    
                def update(self, instance, validated_data):
                    """
                    Update and return an existing `Snippet` instance, given the validated data.
                    """
                    instance.title = validated_data.get('title', instance.title)
                    instance.code = validated_data.get('code', instance.code)
                    instance.linenos = validated_data.get('linenos', instance.linenos)
                    instance.language = validated_data.get('language', instance.language)
                    instance.style = validated_data.get('style', instance.style)
                    instance.save()
                    return instance
    
        - 创建Serializer,简便
            class SnippetSerializer(serializers.ModelSerializer):
                class Meta:
                    model = Snippet
                    fields = ('id', 'title', 'code', 'linenos', 'language', 'style') 
            
            # 和上面是一样的,ModelSerializer里面定义了create,update方法
            # 不信你执行下面语句
                serializer = SnippetSerializer()
                print(repr(serializer))
            
            
        - 添加数据(添加两条数据)
            python manage.py shell
            >>>from snippets.models import Snippet
            >>> snippet = Snippet(code='foo = "bar"
    ')
            >>> snippet.save()
            >>>
            >>>
            >>> snippet = Snippet(code='print "hello, world"
    ')
            >>> snippet.save()
    
        - 使用serializer 得到dict数据 : serializer对象.data
            >>> snippet = Snippet.objects.all()[1]
            >>> serializer = SnippetSerializer(snippet)
            >>> serializer.data
            {'style': 'friendly', 'code': u'print "hello, world"
    ', 'language': 'python', 'title': u'', 'linenos': False, 'id': 2}
        
        - 使用serializer得到Json数据  --序列化
            >>> from rest_framework.renderers import JSONRenderer
            >>> snippet = Snippet.objects.all()[1]
            >>> serializer = SnippetSerializer(snippet)
            >>> content= JSONRenderer().render(serializer.data)
            >>> content
            '{"id":2,"title":"","code":"print \"hello, world\"\n","linenos":false,"language":"python","style":"friendly"}'
            >>>
    
        - 使用serializer反序列化得到字典数据
    
            >>> from rest_framework.renderers import JSONRenderer
            >>> content= JSONRenderer().render(serializer.data)
            >>> content
            '{"id":2,"title":"","code":"print \"hello, world\"\n","linenos":false,"language":"python","style":"friendly"}'
            >>> from rest_framework.parsers import JSONParser
            >>> data = JSONParser().parse(content)
                # 会报错,因为content不是句柄(可读)
                AttributeError: 'str' object has no attribute 'read'
            >>> f = open('a.data','wb')
            >>> f.write(content)
            >>> f.close()
            >>> f = open('a.data','rb')
            >>> data = JSONParser().parse(f)
            >>> data
                {u'style': u'friendly', u'code': u'print "hello, world"
    ', u'language': u'python', u'title': u'', u'linenos': False, u'id': 2}
    
        - 使用serializer插入数据  -- data为上面的data
            >>> serializer = SnippetSerializer(data=data)  # 相当于插入数据
            >>> serializer.is_valid()
            True
            >>> serializer.validated_data
            OrderedDict([(u'title', u''), (u'code', u'print "hello, world"'), (u'linenos', False), (u'language', 'python'), (u'style', 'friendly')])
            >>> serializer.save()
            <Snippet: Snippet object>
            
            # 数据库保存, 查看数据库会发现已经多了一条数据
        
        - 将多个对象序列化many=True
            >>> serializer = SnippetSerializer(Snippet.objects.all(), many=True)
            >>> serializer.data
            [OrderedDict([('id', 1), ('title', u''), ('code', u'foo = "bar"
    '), ('linenos', False), ('language', 'python'), ('style', 'friendly')]), Orde
            redDict([('id', 2), ('title', u''), ('code', u'print "hello, world"
    '), ('linenos', False), ('language', 'python'), ('style', 'friendly')]),
            OrderedDict([('id', 3), ('title', u''), ('code', u'print "hello, world"'), ('linenos', False), ('language', 'python'), ('style', 'friendly')])
            ]
    
        
        - 创建views
            -- 工程.url
                urlpatterns = [
                    url(r'^admin/', admin.site.urls),
                    url(r'^', include('snippets.urls')),
                ]
            -- snippets.url
            urlpatterns = [
                url(r'^snippets/$', views.snippet_list),
                url(r'^snippets/(?P<pk>[0-9]+)/$', views.snippet_detail),
            ]
            -- 视图函数
                # -*- coding: utf-8 -*-
                from __future__ import unicode_literals
    
                from django.shortcuts import render, HttpResponse
                from django.http import JsonResponse
                from snippets.models import Snippet
                from snippets.serializer import SnippetSerializer
    
    
                # Create your views here.
                def snippet_list(request):
                    if request.method == 'GET':
                        snippets = Snippet.objects.all()
                        serializer = SnippetSerializer(snippets, many=True)
                        return JsonResponse(serializer.data, safe=False)
    
    
                def snippet_detail(request, pk):
                    try:
                        snippet = Snippet.objects.get(pk=pk)
                    except Snippet.DoesNotExist:
                        return HttpResponse(status=404)
    
                    if request.method == 'GET':
                        serializer = SnippetSerializer(snippet)
                        return JsonResponse(serializer.data)
    View Code

    -- request,response,fbv

    -# rest-framework核心教程(request, response, api_view, APIVIEW)
        -- request
            # 继承HttpRequest
            # request.data属性相比HttpRequest.POST更灵活:处理更复杂数据且对POST,PUT,PATCH请求都有效
                request.POST  # Only handles form data.  Only works for 'POST' method.
                request.data  # Handles arbitrary data.  Works for 'POST', 'PUT' and 'PATCH' methods.
        -- response
            # 根据客户端请求不同的数据而渲染相应数据
            return Response(data)  # Renders to content type as requested by the client.
        -- status code
            # 可读性更好,而且包含错误信息
        -- 装饰器
            -- fbv装饰器
                @api_view是 工作fbv, 对cbv没有效果的
            -- cbv装饰器
                APIView是对FBV有效果
            -- 好处:
                a.保证了view接收到的request实例
                b.会将context添加到response中
                c.还会返回正确的状态码
                
        -- 使用上面四个核心东西(不再用JSONResponse)
        
            # -*- coding: utf-8 -*-
            from __future__ import unicode_literals
    
            from django.shortcuts import render, HttpResponse
            # from django.http import JsonResponse
            from rest_framework.response import Response
            from snippets.models import Snippet
            from snippets.serializer import SnippetSerializer
    
            from rest_framework.decorators import api_view
            from rest_framework import status
    
    
            @api_view(['GET','POST'])
            def snippet_list(request):
                if request.method == 'GET':
                    snippets = Snippet.objects.all()
                    serializer = SnippetSerializer(snippets, many=True)
                    return Response(serializer.data)
                elif request.method == 'POST':
                    # add snippet obj
                    serializer = SnippetSerializer(data=request.data) # 注意这里版本不同可能不一样python3应该是data=request.DATA
                    if serializer.is_valid():
                        serializer.save()
                        return Response(serializer.data, status=status.HTTP_201_CREATED)
                    else:
                        return Response(serializer.errors,status=status.HTTP_400_BAD_REQUEST)
        
        
        -- 控制渲染给客户端数据的格式
            -- 要修改一些东西
                -- 首先是要先设置url
                    from django.conf.urls import patterns, url
                    from rest_framework.urlpatterns import format_suffix_patterns
    
                    urlpatterns = [
                        url(r'^snippets/$', 'snippet_list'),
                        url(r'^snippets/(?P<pk>[0-9]+)$', 'snippet_detail'),
                    ]
    
                    urlpatterns = format_suffix_patterns(urlpatterns)
                
                -- 其次,要修改view,每个视图函数添加format=None参数
                
                
            -- 使用
                -- 默认是api (浏览器看到)
                    http://127.0.0.1:8000/snippets/
                
                -- 使用Accept头部信息控制response返回格式:
                    curl http://127.0.0.1:8000/snippets/ -H 'Accept: application/json'  # JSON
                
                -- 通过url的后缀来控制response返回格式
                    curl http://127.0.0.1:8000/snippets/.json
                    curl http://127.0.0.1:8000/snippets/.api
        
        -- 控制提交数据的格式 提示request.DATA的灵活性
            以前提交数据都是通过表单提交, -d  后面接的字符串格式 "key=value"
                curl -X POST http://127.0.0.1:8000/snippets/ -d "code=print 123"
            
            使用Json提交 注意多了-H , -d的数据是Json
                curl -X POST http://127.0.0.1:8000/snippets/ -d '{"code": "print 456"}' -H "Content-Type: application/json"
            
        
        -- 测试
            - windows使用curl
                -- 下载curl
                    https://curl.haxx.se/download.html
                -- 解压将curl.exe拷贝到工程目录
                
                -- 执行curl http://127.0.0.1:8000/snippets/
            
            - get 
                --  curl http://127.0.0.1:8000/snippets/
            
            - post
                -- curl -X POST http://127.0.0.1:8000/snippets/ -d "code=print 123"
    View Code

    -- CBV

    -# 使用CBV缩减代码和解耦
        - 使用CBV, url注意 as_view()
            urlpatterns = [
                url(r'^snippets/$', views.SnippetList.as_view()),
                url(r'^snippets/(?P<pk>[0-9]+)/$', views.SnippetDetail.as_view()),
            ]
                
        - 视图类的编写继承APIVIEW, 
            from snippets.models import Snippet
            from snippets.serializer import SnippetSerializer
            from django.http import Http404
            from rest_framework.views import APIView
            from rest_framework.response import Response
            from rest_framework import status
    
    
            class SnippetList(APIView):
                """
                List all snippets, or create a new 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)
    
    
            class SnippetDetail(APIView):
                """
                Retrieve, update or delete a snippet instance.
                """
    
                def get_object(self, pk):
                    try:
                        return Snippet.objects.get(pk=pk)
                    except Snippet.DoesNotExist:
                        raise Http404
    
                def get(self, request, pk, format=None):
                    snippet = self.get_object(pk)
                    serializer = SnippetSerializer(snippet)
                    return Response(serializer.data)
    
                def put(self, request, pk, format=None):
                    snippet = self.get_object(pk)
                    serializer = SnippetSerializer(snippet, data=request.data)
                    if serializer.is_valid():
                        serializer.save()
                        return Response(serializer.data)
                    return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
    
                def delete(self, request, pk, format=None):
                    snippet = self.get_object(pk)
                    snippet.delete()
                    return Response(status=status.HTTP_204_NO_CONTENT)
    View Code

    -- GCBV

    -# 使用GCBV缩减代码, 代码超简单
        from snippets.models import Snippet
        from snippets.serializer 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
    View Code

    -- 验证和权限

    -# 验证和权限
    # 验证(登录)和权限
    
        - 只有经过登录后的用户才能具备某些权限
        
        - 自定义一些权限,来设置某些视图函数的权限
        
    
    # 需求
        - 增加权限: 只有登录后才能创建snippet, 否则只能查看, 对应的视图函数为Snippet_list
         
        - 增加权限: 只有代码的创建者,才能修改, 否则只能查看, 对应的视图函数为Snippet_detail
    
    # 设计
        - 登录验证
            创建者owner关联到User, 利用django rest framework 的permissions中的IsAuthoridOrReady
        
        - 创建者才能修改
            - 创建者字段owner,
            - 创建权限类,自定义只有创建者才能修改
        
        - 核心
            - 关联           -- models.py
            - serializer    -- serialziers.py    
            - 自定义权限    -- permission.py    
            - 登录权限        -- rest_framework.permisson.IsAuthenticatedOrReadOnly
            
        - 补充
            - 页面出现登录button -- project level urls.py
                urlpatterns += [
                    url(r'^api-auth/', include('rest_framework.urls',
                                               namespace='rest_framework')),
                ]
                
            - 关联
                    def perform_create(self, serializer):
                        serializer.save(owner=self.request.user)
            
    -# 实现
        -- models.py
            # -*- coding: utf-8 -*-
            from __future__ import unicode_literals
    
            from django.db import models
            from django.contrib.auth.models import User
            from pygments.lexers import get_all_lexers
            from pygments.styles import get_all_styles
            from pygments.lexers import get_lexer_by_name
            from pygments.formatters.html import HtmlFormatter
            from pygments import highlight
    
            LEXERS = [item for item in get_all_lexers() if item[1]]
            LANGUAGE_CHOICES = sorted([(item[1][0], item[0]) for item in LEXERS])
            STYLE_CHOICES = sorted((item, item) for item in get_all_styles())
    
    
            class Snippet(models.Model):
                created = models.DateTimeField(auto_now_add=True)
                title = models.CharField(max_length=100, blank=True, default='')
                code = models.TextField()
                linenos = models.BooleanField(default=False)
                language = models.CharField(choices=LANGUAGE_CHOICES, default='python', max_length=100)
                style = models.CharField(choices=STYLE_CHOICES, default='friendly', max_length=100)
    
                # add two fields, one is owner field, which is used to represent the user who create the snippet
                # other one is highlighted field, will be used to store the highlighted HTML
                owner = models.ForeignKey(User, related_name="snippets", on_delete=models.CASCADE)
                highlighted = models.TextField()
    
                class Meta:
                    ordering = ('created',)
    
                # overwrite save(self,)
                # 当save()时,需要将高亮HTML写到highligthed里面
    
    
                def save(self, *args, **kwargs):
                    """
                    Use the `pygments` library to create a highlighted HTML
                    representation of the code snippet.
                    """
                    lexer = get_lexer_by_name(self.language)
                    linenos = self.linenos and 'table' or False
                    options = self.title and {'title': self.title} or {}
                    formatter = HtmlFormatter(style=self.style, linenos=linenos,
                                              full=True, **options)
                    self.highlighted = highlight(self.code, lexer, formatter)
                    super(Snippet, self).save(*args, **kwargs)
    
        -- serializers.py
            # -*- coding: utf-8 -*-
            from django.contrib.auth.models import User
            from newsnippets.models import Snippet
            from rest_framework import serializers
    
    
            class SnippetSerializer(serializers.ModelSerializer):
                owner = serializers.CharField(source="owner.username", read_only=True)
    
                class Meta:
                    model = Snippet
                    fields = ('id', 'title', 'code', 'linenos', 'language', 'style', 'owner')
    
            # 因为已经关联User, 所以一定要序列化
            class UserSerializer(serializers.ModelSerializer):
                snippets = serializers.PrimaryKeyRelatedField(many=True, queryset=Snippet.objects.all())
    
                class Meta:
                    model = User
                    fields = ('id', 'username', 'snippets')
    
        -- views.py
            # -*- coding: utf-8 -*-
            from __future__ import unicode_literals
    
            from newsnippets.models import Snippet
            from newsnippets.serializers import SnippetSerializer
            from rest_framework import generics
            from rest_framework import permissions
            from newsnippets.permissions import IsOwnerOrReadOnly
    
    
            class SnippetList(generics.ListCreateAPIView):
                queryset = Snippet.objects.all()
                serializer_class = SnippetSerializer
                # 只有经过验证的request才能修改
                # 没有经过验证的request只能查看
                permission_classes = (permissions.IsAuthenticatedOrReadOnly,
                                      IsOwnerOrReadOnly)
    
                # 将snippet和user关联起来,因为user是通过request传进来的
                # 解决办法是重写perform_create
                def perform_create(self, serializer):
                    serializer.save(owner=self.request.user)
    
    
            class SnippetDetail(generics.RetrieveUpdateDestroyAPIView):
                queryset = Snippet.objects.all()
                serializer_class = SnippetSerializer
    
                # def perform_create(self, serializer):
                #     serializer.save(owner=self.request.user)
    
                permission_classes = (permissions.IsAuthenticatedOrReadOnly,
                                      IsOwnerOrReadOnly)
    
    
            from django.contrib.auth.models import User
            from newsnippets.serializers import UserSerializer
    
    
            class UserList(generics.ListAPIView):
                queryset = User.objects.all()
                serializer_class = UserSerializer
    
    
            class UserDetail(generics.RetrieveAPIView):
                queryset = User.objects.all()
                serializer_class = UserSerializer
    
        -- 登录权限
            from rest_framework import permissions.IsAuthenticatedOrReadOnly
        
        -- 自定义权限
        
            # -*- coding: utf-8 -*-
            from rest_framework import permissions
    
    
            # 需要添加一个权限:只有创建者才能修改,或者只能查看
            # 之后见权限添加到views里面的permission_classes
            class IsOwnerOrReadOnly(permissions.BasePermission):
                """
                Custom permission to only allow owners of an object to edit it.
                """
    
                def has_object_permission(self, request, view, obj):
                    # Read permissions are allowed to any request,
                    # so we'll always allow GET, HEAD or OPTIONS requests.
                    if request.method in permissions.SAFE_METHODS:
                        return True
    
                    # Write permissions are only allowed to the owner of the snippet.
                    return obj.owner == request.user    
        -- 将权限添加到views
             permission_classes = (permissions.IsAuthenticatedOrReadOnly,
                              IsOwnerOrReadOnly)
        
        -
    View Code

    -- 超链接实现不同model之间跳转,分页

    - #超链接提供模型之间的关联
        存在问题:
            - 访问http://127.0.0.1:8000/users/时看到的用户列表,
              没有提供链接,指点点击链接可以查看某个用户的详情,比如不能跳转到http://127.0.0.1:8000/users/2
             
            - 访问http://127.0.0.1:8000/snippets/同样存在问题
            
            - 而且users 和snippets没有跳转
            
        解决问题:
            - 设计根url(首页/),该页面可以访问所有模型(snippet和user)
               # views.py增加一个view , 这里采用fbv
               
                from rest_framework.decorators import api_view
                from rest_framework.response import Response
                from rest_framework.reverse import reverse
    
    
                @api_view(['GET'])
                def api_root(request, format=None):
                    return Response({
                        'users': reverse('user-list', request=request, format=format),
                        'snippets': reverse('snippet-list', request=request, format=format)
                    })
        
                # 注意还需要设置    /  ---> api_root的映射关系
                
                # 模板也已经设置了
                
                # reverse,所以user-list是某个url的name, 之后一定要设置
            
                # 目前访问首页的结果, 可以提供了超链接跳转到users, 和snippets
                    Api Root
                    GET /
                    HTTP 200 OK
                    Allow: OPTIONS, GET
                    Content-Type: application/json
                    Vary: Accept
    
                    {
                        "users": "http://127.0.0.1:8000/new/users/",
                        "snippets": "http://127.0.0.1:8000/new/snippets/"
                    }
             
            - 添加超链接,当点击超链接时可以看到高亮代码--返回html,如果返回json,那可视化就不行了;
                # 返回html
                    REST framework为我们提供了两种方式来呈现HTML,一种是使用已有的模板(我们平时开发Django更常用的那种方式),另一种就是使用已经构建好的HTML代码。在这里我们会使用第二种方法
                    刚才已经说了每次保存数据时都会自动更新生成新的HTML代码,而这个由pygments生成的代码就保存在Snippet下的highlighted,所以有浏览器渲染并呈现highlighted下的HTML代码就行了。
                    
                    renderer_classes = (renderers.StaticHTMLRenderer,)
            
                # 编写GCBV
                    from rest_framework import renderers
                    from rest_framework.response import Response
    
                    class SnippetHighlight(generics.GenericAPIView):
                        queryset = Snippet.objects.all()
                        renderer_classes = (renderers.StaticHTMLRenderer,)
    
                        def get(self, request, *args, **kwargs):
                            snippet = self.get_object()
                            return Response(snippet.highlighted)
                
                # 编写url
                    url(r'^snippets/(?P<pk>[0-9]+)/highlight/$', views.SnippetHighlight.as_view()),
                    
                
                # 测试
                    浏览器输入:
                    http://127.0.0.1:8000/new/snippets/1/highlight/
            
            
            - 将高亮代码超链接添加到new/snippet/1/页面
                # 修改SnippetSerailizer添加一个highlight字段,并且设置值为超链接,
                    highlight = serializers.HyperlinkedIdentityField(view_name='snippet-highlight', format='html')
                    注意view_name参数,命名空间, format="html", html显示高亮代码
                # fields
                    fields = ('url', 'id', 'highlight', 'owner',
                      'title', 'code', 'linenos', 'language', 'style')
                    
                    注意多了个url, highlight
                    
                # 测试
                    http://127.0.0.1:8000/new/snippets/1/
                    可以看到
                    {
                        "url": "http://127.0.0.1:8000/new/snippets/1/",
                        "id": 1,
                        "title": "test 1",
                        "highlight": "http://127.0.0.1:8000/new/snippets/1/highlight/",
                        "code": "a = 2",
                        "linenos": true,
                        "language": "python3",
                        "style": "friendly",
                        "owner": "lzp"
                    }
                    
            - 将snippet超链接添加到user页面, 即可以看到
                    snippets = serializers.HyperlinkedRelatedField(many=True, view_name='snippet-detail', read_only=True)
    
                # 测试
                    http://127.0.0.1:8000/new/users/
                    
                    HTTP 200 OK
                    Allow: GET, HEAD, OPTIONS
                    Content-Type: application/json
                    Vary: Accept
    
                    [
                        {
                            "url": "http://127.0.0.1:8000/new/users/1/",
                            "id": 1,
                            "username": "lzp",
                            "snippets": [
                                "http://127.0.0.1:8000/new/snippets/1/"  # 可以看到所有snippets的超链接
                            ]
                        }
                    ]
                
            - 分页
                REST_FRAMEWORK = {
                    'PAGE_SIZE': 10
                }
    View Code
  • 相关阅读:
    binutils工具集之---objcopy,ranlib,size,strings,strip
    FreeRtos——多任务
    IntelliJ Idea 常用快捷键
    了解Spring-boot-starter常用依赖模块
    Spring Boot项目的内嵌容器
    Spring Boot 简介
    webstorm的个性化设置settings
    webstorm使用心得
    webstorm快捷键
    WebStorm使用快速入门
  • 原文地址:https://www.cnblogs.com/liuzhipenglove/p/7988403.html
Copyright © 2011-2022 走看看