django rest-framework 4.REST的认证和权限
目前,我们的API对谁可以编辑或删除代码段没有任何限制。我们想要一些更先进的行为,以确保:(这段话抄自官网)
- 代码段始终与创建者相关联。
- 只有身份验证的用户可以创建片段。
- 只有片段的创建者可以更新或删除它。
- 未经身份验证的请求应具有完全只读访问权限。
一、将信息添加至 model
使用官方例子在表中添加用户字段,该字段用来判断是否与登录用户有关系。
owner = models.ForeignKey('auth.User', related_name='snippets', on_delete=models.CASCADE) highlighted = models.TextField()
这里的owner用户关联的为django admin的认证用户,该字段用与匹配登录用户是否有权限修改该数据(后面涉及到)。
二、为用户模型添加端点
为 auth.User 表添加到api中,首先需要添加序列化。由于snippets(这里的smippets为外键的related_name,默认为"表名_set")在用户模型上是反向关系,所以在使用ModelSerializer 类时它不会被默认包含,需要添加一个显示的字段。
# 用户序列化函数 serializers.py from django.contrib.auth.models import User class UserSerializer(serializers.ModelSerializer): snippets = serializers.PrimaryKeyRelatedField(many=True, queryset=Snippet.objects.all()) class Meta: model = User fields = ('id', 'username', 'snippets') # 用户视图函数 views.py from django.contrib.auth.models import User from snippets.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 # 配置URL conf url(r'^users/$', views.UserList.as_view()), url(r'^users/(?P<pk>[0-9]+)/$', views.UserDetail.as_view()),
三、snippets 和 user 关联
关联用户通过重写SnippetList 视图类的 perform_create(),该方法修改实例保存的管理方式,并处理传入请求或request中的任何信息。
在SnippetList
视图类上,添加以下方法:(个人理解:使保存的数据用户字段为登录用户的信息)
def perform_create(self, serializer): serializer.save(owner=self.request.user)
四、更新serializer
snippets 和 user关联后,在snippets中owner的信息默认为id信息,更新序列化类(serializer)是owner显示为用户名信息。
# 更新 SmippetSerializer 添加如下: owner = serializers.ReadOnlyField(source='owner.username') # 并确保 fields 中有owner字段。
我们添加的是无类型的 ReadOnlyField 类,与其他类型的字段(CharField,BooleanField等)相比ReadOnlyField 总是只读的。如果设置为ReadOnlyField 该字段则不用用于更新(但是参数还是会传递到后端。),我们也可以使用CharField(read_only=Ture)来指定字段类型并且设置为只读字段。
五、为视图添加权限
既然Snippet和user相关联,我们希望只有经过身份验证的用户才能创建,更新和删除代码片段。
REST框架包含许多权限类,我们可以使用这些权限类来限制可以访问给定视图的人员。在这种情况下,我们正在寻找的是IsAuthenticatedOrReadOnly
确保经过身份验证的请求获得读写访问权限,未经身份验证的请求获得只读访问权限。
首先在视图模块中添加以下导入:
from rest_framework import permissions
接着,下面的属性添加到都在SnippetList
和SnippetDetail
视图类。
permission_classes = (permissions.IsAuthenticatedOrReadOnly,)
六、添加登录API
在适当的urls.py文件中天剑URLconf在添加可浏览API的登录视图。
from django.conf.urls import include # 按需添加如下urlconf,r'^api-auth/'模式的部分实际上可以是您想要使用的任何URL。 urlpatterns += [ url(r'^api-auth/', include('rest_framework.urls')), ]
七、对象级权限
我们希望所有人都可以看到所有代码片段,但也要确保只有创建代码段的用户才能更新或删除它。为此,我们需要创建一个自定义权限。
在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. # 否则判断用户是否与操作数据的用户相同,返回Ture or False return obj.owner == request.user
添加完之后在SnippetDetail类视图中添加 permission_classes属性来将该自定义权限加到代码中:
记得导入 IsOwnerOrReadOnly (from snippets.permissions import IsOwnerOrReadOnly
)
permission_classes = (permissions.IsAuthenticatedOrReadOnly,IsOwnerOrReadOnly,)