Django REST FrameWork中文教程4:认证和权限
目前,我们的API对谁可以编辑或删除代码段没有任何限制。我们希望有更高级的行为,以确保:
在我们的模型(model)中添加信息Snippet模型类进行几次更改。首先,我们添加几个字段。其中一个字段将用于表示创建代码段的用户,另一个字段将用于存储代码的高亮显示的HTML内容。 将以下两个字段添加到 owner?=?models.ForeignKey('auth.User',?related_name='snippets',?on_delete=models.CASCADE) highlighted?=?models.TextField() 我们还需要确保在保存模型时,使用 我们需要导入额外的模块: from?pygments.lexers?import?get_lexer_by_name from?pygments.formatters.html?import?HtmlFormatter from?pygments?import?highlight 现在我们可以在我们的模型类中添加一个. def?save(self,?*args,?**kwargs): ????""" ?????使用`pygments`库创建一个高亮显示的HTML表示代码段。 ????""" ????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) 完成这些工作后,我们需要更新我们的数据库表。 通常这种情况我们会创建一个数据库迁移(migration)来实现这一点,但现在我们只是个教程示例,所以我们选择直接删除数据库并重新开始。 rm?-f?tmp.db?db.sqlite3 rm?-r?snippets/migrations python?manage.py?makemigrations?snippets python?manage.py?migrate 你可能还需要创建几个不同的用户,以用于测试API。最快的方法是使用 python?manage.py?createsuperuser 为我们的用户模型添加路径现在我们已经创建了一些用户,我们最好在API中添加这些用户的表示。创建一个新的序列化器非常简单,在 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') 'snippets'在用户模型中是一个反向关联关系。在使用 我们还会在views.py中添加几个视图。我们只想将用户展示为只读视图,因此我们将使用 from?django.contrib.auth.models?import?User class?UserList(generics.ListAPIView): ????queryset?=?User.objects.all() ????serializer_class?=?UserSerializer class?UserDetail(generics.RetrieveAPIView): ????queryset?=?User.objects.all() ????serializer_class?=?UserSerializer 确保也导入 from?snippets.serializers?import?UserSerializer 最后,我们需要通过从URL conf引用它们将这些视图添加到API中。将以下内容添加到 url(r'^users/$',?views.UserList.as_view()),url(r'^users/(?P<pk>[0-9]+)/$',?views.UserDetail.as_view()), 将Snippet和用户关联现在,如果我们创建了一个代码片段,并不能将创建该代码片段的用户与代码段实例相关联。用户不是作为序列化表示的一部分发送的,而是作为传入请求的属性。(译者注:user不在传过来的数据中,而是通过request.user获得) 我们处理的方式是在我们的代码片段视图中重写一个 在 def?perform_create(self,?serializer): ????serializer.save(owner=self.request.user) 我们的序列化器的create()方法现在将被传递一个附加的 更新我们的序列化器现在,这些代码片段和创建它们的用户相关联,让我们更新我们的 owner?=?serializers.ReadOnlyField(source='owner.username') 注意:确保您还将 这个字段非常有趣。 我们添加的字段是无类型的 添加视图所需的权限现在,代码片段与用户是相关联的,我们希望确保只有经过身份验证的用户才能创建,更新和删除代码片段。 REST框架包括许多权限类,我们可以使用这些权限类来限制谁可以访问给定的视图。 在这种情况下,我们需要的是 首先要在视图模块中导入以下内容 from?rest_framework?import?permissions 然后,将以下属性添加到 permission_classes?=?(permissions.IsAuthenticatedOrReadOnly,) 给Browsable API添加登陆如果你打开浏览器并浏览我们的API,那么你会发现不能创建新的代码片段。只有登陆用户才能创建新的代码片段。 我们可以通过编辑项目级别的 在文件顶部添加以下导入: from?django.conf.urls?import?include 并且,在文件末尾,添加一个模式以包括可浏览的API的登录和注销视图。 urlpatterns?+=?[ ????url(r'^api-auth/',?include('rest_framework.urls',???????????????????????????????namespace='rest_framework')),] 模式的 现在,如果你再次打开浏览器并刷新页面,你将在页面右上角看到一个“登录”链接。如果你用早期创建的用户登录,就可以再次创建代码片段。 一旦你创建了一些代码片段后,在'/users/'路径下你会注意到每个用户的'snippets'字段都包含与每个用户相关联的代码片段的列表。 对象级别的权限我们希望所有的代码片段都可以被任何人看到,但也要确保只有创建代码片段的用户才能更新或删除它。 为此,我们将需要创建一个自定义权限。 在snippets app中,创建一个新文件? 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 现在,我们可以通过在 确保先导入 |