首页 > 代码库 > django-rest-framework学习之Authentication & Permissions--2017年4月14日

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

Authentication & Permissions
 
参考:http://www.cnblogs.com/hillfree/archive/2013/03/26/django-rest-framework-tutorial-04.html
 
认证和权限
目前我们的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 created a highlighted HTML
    representation of code myLesson
    """
    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,**kwargs)
    self.highlighted = highlight(self.code,lexer,fomatter)
    super(MyLesson,self).save(*args,**kwargs)

 

然后更新数据库表单,通常我们会迁移数据库,但是在这里,我们直接删掉重新开始
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,)

 

 

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