Django REST framework 第四章 Authentication
到目前为止,撰写的API没有任何限制关于谁能更新、删除snippet. 我们更想要一些高级行为来确保:
1、代码段总是跟创建者有关联
2、只要认证通过的用户才能创建
3、只有创建者有权限更新或者删除
4、没有认证的请求应该有且只有完全的只读权限
Adding information to our model
我们打算在Snippet模型类上做一些改变。首先,添加一些字段,其中之一用来代表创建这个code的用户。其他的字段将用于存储代码中突出显示的HTML表示形式。
添加下面两个字段到Snippet类在models.py.
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
现在需要往model类里面添加一个save方法:
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 = 'table' if self.linenos else False
options = {'title': self.title} if self.title else {}
formatter = HtmlFormatter(style=self.style, linenos=linenos,
full=True, **options)
self.highlighted = highlight(self.code, lexer, formatter)
super(Snippet, self).save(*args, **kwargs)
做好上面的操作后,需要同步数据库
shuais-MacBook-Pro:TestApp dandyzhang$ rm -f db.sqlite3
shuais-MacBook-Pro:TestApp dandyzhang$ rm -r app01/migrations
shuais-MacBook-Pro:TestApp dandyzhang$ python3 manage.py makemigrations
shuais-MacBook-Pro:TestApp dandyzhang$ python3 manage.py migrate
为了测试API,还需要创建一下超级用户:
shuais-MacBook-Pro:TestApp dandyzhang$ python3 manage.py createsuperuser
Adding endpoints for our User models
现在我们已经有一些工作的用户了,还需要添加这些用户的表示到API中。
在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')
snippets在 User model上是一种反转关系,在继承ModelSerializer类不能使用默认值。所以需要为它添加一个明确的字段
同样,也需要在views.py文件内添加一些东西。我们更倾向于为用户表示使用只读权限,所以我们将使用ListAPIView和RetrieveAPIView generic CBV.
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
确认下导入的UserSerializer类
from app01.serializers import UserSerializer
最后,我们需要把这些视图添加进API,通过url设置,在urls.py文件中
path('users/', views.UserList.as_view()),
path('users/<int:pk>/', views.UserDetail.as_view()),
Associating Snippets with Users
现在,如果我们创建snippet,会发现没有办法通过snippet实例关联到创建的用户。用户不是作为序列化表示的一部分发送的,而是即将到来的请求的属性。
解决这个问题的方式是重写一个.perform_create()方法在views里面,它允许我们修改管理实例如何保存,处理传入请求或者被请求URL的任何信息
在SnippetList视图类添加如下的方法:
def perform_create(self, serializer):
serializer.save(owner=self.request.user)
一个额外添加的owner字段现在将会被serializer里面的create方法通过,跟请求里面的验证数据一起。
Updating our serializer
现在snippets和用户的关联建好了,更新一下SnippetSerializer来反应它。在serializers.py文件添加:
owner = serializers.ReadOnlyField(source='owner.username')
注意将它添加在Meta类内部的字段列表中.
class SnippetSerializer(serializers.ModelSerializer):
owner = serializers.ReadOnlyField(source='owner.username') class Meta:
model = Snippet
fields = ('id', 'title', 'code', 'linenos', 'language', 'style', 'owner')
这个字段做了些很有趣的事情。source参数控制一种属性用来跟某个字段关联对应,可以指向序列化实例的任何属性。它也可以采用上面所显示的实例的表示法,将会遍历给定的属性,跟Django的模版语言很类似。
我们刚刚添加的这个字段是一个非类型化的ReadOnlyField类,与其他类型字段相反,比如CharField、BooleanField等...非类型话的ReadOnlyField总是只读的,并将用于序列化表示,但是在反序列化的时候不能被用来更新模型实例,也可以用CharField(read_only=True)
Adding required permissions to views
现在snippet已经跟用户有联系了,我们想确定只有通过验证的用户可以创建,更新,删除snippet。
REST framework包含了一串权限类供用来限制谁能访问一个给定的视图。在这里,我们想要寻找的是IsAuthenticatedOrReadOnly这个类用来确保通过验证的请求获取到读写权限,没有通过验证的请求获得只读权限。
首先在views里面导入模块
from rest_framework import permissions
然后添加下面的属性到SnippetList和SnippetDetail两个视图类中。
permission_classes = (permissions.IsAuthenticatedOrReadOnly,)
Adding login to Browable API
如果你打开浏览器,导航到了可浏览的API,你会发现你不能再创建新的spnippet了。为了能这样做,需要先登陆。
我们可以再根目录的urls文件内加入下面的路由,它包含可浏览的API的登陆和登出。
path('api/', include('rest_framework.urls', namespace='rest_framework')),
路由的名称可以自定义。
现在打开浏览器,你会在网页的右上角看到login的图标。如果你用之前创建的用户登陆了,你就可以再一次创建snippet了。
创建好一些snippet后,你就可以在子路由users下面查看到


Object level permissions
我们想让所有的snippet被任何人看到,但必须保证只有创建的人才可以增删改。
想要这么做,需要创建一个定制化的权限。创建一个新的文件在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
现在可以添加自定义的权限到snippet实例终端,通过编辑在SnippetDetail视图类里面的permission_classes属性
from app01.permissions import IsOwnerOrReadOnly # 先导入 permission_classes = (permissions.IsAuthenticatedOrReadOnly,
IsOwnerOrReadOnly,)
现在重新运行一下此项目,你会发现delete和put按钮出现在你创建的一个snippet实例的终端。
Authenticating with the API
因为现在已经有一批权限在API上,如果需要编辑任何的snippet需要认证请求。但是我们还没有设置任何的认证类,所以此时是使用的默认的类SessionAuthentication和BasicAuthentication
当我们通过浏览器跟API进行交互,我们可以登陆,然后浏览器的session会提供必要的认证给请求。如果我们以变成的方式跟API交互,就需要提供明确的认证凭据在每一次请求上。如果尝试创建一个新的snippet不带验证,将会得到报错:

带上认证凭据:

Django REST framework 第四章 Authentication的更多相关文章
- django by example 第四章 dashboard处html无法渲染问题
描述: 实现django by example 代码时,第四章 dashboard处html无法渲染问题. 此时报错,NoReverseMatch at /account/login/, Error ...
- (转)Django学习之 第四章:Django模板系统
前面的章节我们看到如何在视图中返回HTML,但是HTML是硬编码在Python代码中的 这会导致几个问题: 1.显然,任何页面的改动会牵扯到Python代码的改动 网站的设计改动会比Python代码改 ...
- Django REST framework 第六章 ViewSets & Routers
REST framework包含了一个可以处理ViewSets的抽象, 它允许开发人员专注于API的状态跟交互进行建模,并使得URL构建结构基于通用的约定自动处理. ViewSet类跟View类几乎相 ...
- Django REST framework 第五章 Relationships & Hyperlinked APIs
到目前为止,API内部的关系是使用主键来代表的.在这篇教程中,我们将提高API的凝聚力和可发现性,通过在相互关系上使用超链接. Creating an endpoint for the root of ...
- Django REST framework 第三章 CBV
从介绍Django快开始,我们就一直在使用FBV的方式来撰写代码,二者本质上并没有太大的区别,然而到了REST framework,更会倾向于用CBV来写API的视图,后面会看到这个方式的强大,它允许 ...
- Django REST framework 第七章 Schemas & client libraries
模式是一个机器可读文档,描述可用的API端点,URL以及它们支持的操作. 模式对于自动生成文档是一个很有用的工具,也可以用来动态调用可以于API交互的客户端库. Core API 为了提供模式支持,R ...
- django by example 第四章 扩展 User 模型( model)
描述: RelatedObjectDoesNotExist at /account/edit/ User has no profile. 原因: 注意原书,要求新建一个账户才能使用.
- Django Rest framework实现流程
目录 一 什么是restful架构 二 Django REST framework简介 三 Django REST framework原理 四 Django REST framework源码流程 五 ...
- 《Django By Example》第四章 中文 翻译 (个人学习,渣翻)
书籍出处:https://www.packtpub.com/web-development/django-example 原作者:Antonio Melé (译者注:祝大家新年快乐,这次带来<D ...
随机推荐
- 汇编 gdb调试
as -g --32 -o hello.o hello.s ld -m elf_i386 -o hello hello.o gdb hello
- 第八节,配置分布式TensorFlow
由于随着神经网络层数的增多,需要训练的参数也会增多,随之而来需要的数据集就会很大,这样会造成需要更大的运算资源,而且还要消耗很长的运算时间.TensorFlow提供了一个可以分布式部署的模式,将一个训 ...
- Oracle的DQL
基本查询: 链接语句: sqlplus scott/tiger@192.168.56.101:1521/orcl SQL> --清屏 SQL> host cls (host clear) ...
- 你真的知道什么是【共享Session】,什么是【单点登录】吗?
一直有人问,为什么我实现的共享session不能单点登录,今天我也抽时间准备好好说一下. 我要喷(别喷我) 首先,网上水货文章很多,CSDN居多.CSDN转载率很高,也就是说同相同文章有很多,换汤不换 ...
- POJ 3352 Road Construction ; POJ 3177 Redundant Paths (双联通)
这两题好像是一样的,就是3177要去掉重边. 但是为什么要去重边呢??????我认为如果有重边的话,应该也要考虑在内才是. 这两题我用了求割边,在去掉割边,用DFS缩点. 有大神说用Tarjan,不过 ...
- STM32F4 ------ RTC
如果只执行 HAL_RTC_GetTime(),读取完后时间不再跑 HAL_RTC_GetTime() 和 HAL_RTC_GetDate()
- 【简单易用的傻瓜式图标设计工具】Logoist 3.1 for Mac
[简介] Logoist 是一款Mac上强大易用的傻瓜式图标设计制作工具,通过使用内置模板和预设效果,您可以立即创建高质量的图形内容和艺术作品.通过使用该应用程序,可用于制作图标LOGO. 一款用于创 ...
- 《Go并发编程实战》读书笔记-初识Go语言
<Go并发编程实战>读书笔记-初识Go语言 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 在讲解怎样用Go语言之前,我们先介绍Go语言的特性,基础概念和标准命令. 一. ...
- Mysql数据库进阶之(分表分库,主从分离)
前言:数据库的优化是一个程序员的分水岭,作为小白我也得去提前学习这方面的数据的 (一) 三范式和逆范式 听起范式这个迟非常专业我来举个简单的栗子: 第一范式就是: 把能够关联的每条数据都拆分成一个 ...
- 理解self与this
刚开始学习Python的类写法的时候觉得很是麻烦,为什么定义时需要而调用时又不需要,为什么不能内部简化从而减少我们敲击键盘的次数?你看完这篇文章后就会明白所有的疑问. self代表类的实例,而非类. ...