Rest framework 学习(4) 身份验证和权限

目前,我们的API对谁可以编辑或删除代码段没有任何限制。我们希望有一些更高级的行为,以确保:

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

修改模型添加信息

将对我们的Snippet模型类进行一些更改。首先,让我们添加几个字段。其中一个字段将用于表示创建代码段的用户。另一个字段将用于存储代码的突出显示的HTML表示。

owner = models.ForeignKey('auth.User', related_name='snippets', on_delete=models.CASCADE)
highlighted = models.TextField()

我们还需要确保在保存模型时,使用pygments代码突出显示库填充突出显示的字段

from pygments.lexers import get_lexer_by_name
from pygments.formatters.html import HtmlFormatter
from pygments import highlight

 完成所有操作后,我们需要更新数据库表。通常我们会创建一个数据库迁移来执行此操作,但是出于本教程的目的,我们只需删除数据库并重新开始。 

# 删除原先的数据库和数据迁移记录
# Linux:
rm -f db.sqlite3
rm -r snippets/migrations

# window:
del db.sqlite3
rd /s/q snippets\migrations


# 数据库生成河迁移
python manage.py makemigrations snippets
python manage.py migrate


# 您可能还想创建一些不同的用户,以用于测试API。最快的方法是使用createsuperuser命令。

python manage.py createsuperuser

 修改用户,实现用户与代码片段的反向关系

  • 修改UserSerializer 序列化器

 

# 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')
  •  修改User相关View.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
  • 修改urls.py:将视图加入到urlpattern 中
# Django version >=2.0
path('users/', views.UserList.as_view()),
path('users/<int:pk>/', views.UserDetail.as_view()),

# Django version <2.0
from django.conf.urls import include,url

url(r'^users/$', views.UserList.as_view()),
url(r'^users/(?P<pk>[0-9]+)/$', views.UserDetail.as_view()),

代码片段与用户关联起来

截至目前,我们有代码段到用户的模型,序列化器,用户的序列化器,能够实现查询时候的相互查询。

但是当我们新建代码时,还是无法实现用户与代码段的互相关联的。

原因是:新建一个代码片段时候,根据已经完成的model(保含有owner),View;但我们需要的用户信息不是想代码code那样在在请求提交的form表单里面的,而是在request.user里。我们还需要对View进行修改。

我们通过的.perform_create()方法是通过覆盖我们的代码段视图上的方法,它允许我们修改实例保存的管理方式,并处理传入请求或请求的URL中隐含的任何信息。 

 

class SnippetList(generics.ListCreateAPIView):
    queryset = Snippet.objects.all()
    serializer_class = SnippetSerializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,)

    def perform_create(self, serializer):
        # 保存之前按,加入owner信息
        # 通过覆盖我们的代码段视图上的方法,允许我们修改实例保存的管理方式,并处理传入请求或请求的URL中隐含的任何信息。
        serializer.save(owner=self.request.user)
  • 更新我们的片段序列化器
class SnippetSerializer(serializers.ModelSerializer):
    owner = serializers.ReadOnlyField(source='owner.username')
    # source 用于填充的字段,连接其他表的任何字段
    # ReadOnlyField 是只读字段,能用于序列化,但不作为更新model使用,效果等价于CharField(read_only=True)

    class Meta:
        model = Snippet
        fields = ('id', 'title', 'code', 'linenos', 'language', 'style','owner')

向视图添加所需权限

既然代码片段与用户相关联,我们希望确保只有经过身份验证的用户才能创建,更新和删除代码段。

REST框架包含许多权限类,我们可以使用这些权限来限制谁可以访问给定视图。在这种情况下,我们正在寻找的是IsAuthenticatedOrReadOnly,这将确保经过身份验证的请求获得读写访问权限,未经身份验证的请求将获得只读访问权限。

  • 首先在snippets\views.py模块中
# snippets\views.py
from rest_framework import permissions

# 在SnippetList和SnippetDetail视图类加入
permission_classes = (permissions.IsAuthenticatedOrReadOnly,)

添加登录到Browsable API

如果您此时打开浏览器并导航到可浏览的API,您将发现您无法再创建新的代码段。为此,我们需要能够以用户身份登录。

我们可以通过编辑项目级urls.py文件中的URLconf来添加用于可浏览API的登录视图。

修改如下:

from django.conf.urls import include
# if Django version >=2.0
。。。
urlpatterns += [
    path('api-auth/', include('rest_framework.urls')),
]
。。。
# else:
urlpatterns += [
    path('api-auth/', include('rest_framework.urls')),
]

打开浏览器访问

 

 对象级权限

实际上,我们希望所有人都可以看到所有代码段,但也要确保只有创建代码段的用户才能更新或删除它。

为此,我们需要创建自定义权限。

在代码段应用中,创建一个新文件, 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

现在,我们可以通过编辑视图类的permission_classes属性将该自定义权限添加到我们的代码段实例端点SnippetDetail

from snippets.permissions import IsOwnerOrReadOnly

permission_classes = (permissions.IsAuthenticatedOrReadOnly,
                      IsOwnerOrReadOnly,)

测试API

不进行身份验证的情况下创建代码段,则会收到错误消息

加了认证后,可以正常请求,换回201Created状态码,对象成功创建。

 总结:

对接口加权限是出于网站安全和业务需要的,主要实现依赖于permission,自定义权限继承permissions.BasePermission重构自己需要的业务权限,结果返波尔值。

 

# 如有理解错误,请指出 #

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值