• django-rest-framework学习之Authentication & Permissions--2017年4月14日


    Authentication & Permissions
     
     
    认证和权限
    目前我们的API对于谁可以编辑和删除MyLesson没有任何限制,我们希望添加一些高级的行为使程序具有如下功能:
    MyLesson有相应的创建者
    只有经过认证的user可以创建MyLesson
    只有MyLesson的创建者可以修改和删除MyLesson
    没有认证的求情只有可读属性
     
    【1】为model增加信息
    改变一些MyLesson的model类,首先添加一对Fields,其中一个用来表示MyLesson的创建者,另外一个存储代码的高亮HTML的表现形式
    owner = models.ForeignKey('auth.User',related_name='myLesson',on_delete=models.CASCADE)   
    highlighted = models.TextField()
     
    # 对于django.db.models,参考官方文档:https://docs.djangoproject.com/en/1.9/ref/models/fields/#model-field-types
    # 文档的右下角可以选择django的版本
    # 本程序使用
    # DateTimeField(auto_now_add=True),
    # CharField(max_length=100, blank=True,default='')
    # TextField()
    # BooleanField(default=False)
    # CharField(choices=LANGUAGE_CHOICES,default='python',max_length=100)
    # ForeignKey('auth.User',related_name='myLesson',on_delete=models.CASCADE)
     
    我们需要确定的是,当model被保存时,我们植入了highlighted field
    使用pygments代码高亮库来完成
    from pygments.lexers import get_lexer_by_name
    from pygments.formatters.html import HtmlFormatter
    from pygments import highlight
    
    
    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(MyLesson, self).save(*args, **kwargs)
    
        # limit the number of instances retained
        myLesson = MyLesson.objects.all()
        if len(myLesson) > 100:
            myLesson[0].delete()
    然后更新数据库表单,通常我们会迁移数据库,但是在这里,我们直接删掉重新开始
    rm -f db.sqlite3
    rm -r myLesson/migrations
    python manage.py makemigrations myLesson
    python manage.py migrate
     
    然后创建几个用户做测试
    python manage.py createsuperuser
     
    【2】为User model增加endpoints
    给API添加User的展示页面
    在serializer.py中:
    from django.contrib.auth.models import User
     
    class UserSerializer(serializers.ModelSerializer):
        myLesson = serializers.PrimaryKeyRelatedField(many=True,queryset=MyLesson.objects.all())   
        class Meta:
            model = User
            fields = ('id','username','myLesson')
    因为MyLesson和User是是反向关联(reverse relationship,即多对一),所以不会默认添加在ModelSerializer类中,我们需要添加一个明确的field
     
    在views.py中我们需要一个只读的view对User做展示,所以我们添加ListAPIView和RetrieveAPIView
    from django.contrib.auth.models import User
    from myLesson.serializers import MyLessonSerializer,UserSerializer
     
    class UserList(generics.ListAPIView):
        queryset = User.objects.all()
        serializer_class = UserSerializer
     
    class UserDetail(generics.RetrieveAPIView):
        queryset = User.objects.all()
        serializer_class = UserSerializer
     

    最后添加这些views到API中,修改urls.py:

    url(r'^users/$',views.UserList.as_view()),
    url(r'^users/(?P<pk>[0-9]+)/$',views.UserDetail.as_view()),
    【3】连接MyLesson和User
    目前,User没有被作为序列化展示的一部分,相反,成了request中的一个属性。
    我们在MyLesson views中重写一个perform_create()方法,允许我们修改 实例如何保存,处理隐藏在request中的信息
    在MyLessonList类中添加:
    def perform_create(self,serializer):
        serializer.save(owner=self.request.user)

    在create方法中传递owner field,还有我们要创建的数据

     
     【4】升级serializer
    在MyLesson中添加owner属性
    class MyLessonSerializer(serializers.ModelSerializer):
        owner = serializers.ReadOnlyField(source='owner.username')
        class Meta:
            model = MyLesson
            fields = ('id','title','code','linenos','language','style','owner')

    ReadOnlyField非常有趣,source参数用来植入一个field,可以用任何Serializer类中的属性,ReadOnlyField可以用CharField(read_only=True)代替

     
    【5】为view添加必要的权限
    我们希望认证用户可以更新,删除,和创建MyLesson
    Rest framework提供了permission类,使我们可以限制谁可以键入一个给定的视图,使用IsAuthenticatedOrReadOnly,来确使认证用户可以读写,其他用户只能只读
    在MyLessonList和MyLessonDetail view类中添加如下属性
    from rest_framework import permissions
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,)
    【6】为API添加登陆
    在项目级别的urls.py中添加以下pattern,允许登入登出
    from django.conf.urls import include
    url(r'^api-auth/', include('rest_framework.urls',namespace='rest_framework')),
    【7】对象级别的权限
    只有对象的创建者可以删除和修改:
    在MyLesson app中添加permissions.py
    from rest_framework import permissions
    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.py中MyLessonDetail中加入
    from myLesson.permissions import IsOwnerOrReadOnly
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,IsOwnerOrReadOnly,)
     
  • 相关阅读:
    CodeForces
    [VS Code] 入门-自定键盘快捷键
    代码格式化工具:clang-format
    用 shell 脚本做 restful api 接口监控
    [apue] 一图读懂 unix 文件句柄及文件共享过程
    Python Django开发的WebSSH 堡垒机
    最好用的流程编辑器bpmn-js系列之基本使用
    树莓派系列(第三篇):树莓派换源 、连接WiFi、安装transmission、samba
    教你用MacBook玩童年FC游戏
    vscode、hbuider编辑器代码片段示例
  • 原文地址:https://www.cnblogs.com/jingbostar/p/6710215.html
Copyright © 2020-2023  润新知