Django-Rest-Framework 教程: 4. 验证和权限

作者: Desmond Chen,

发布日期: 2014-06-01,

修改日期: 2014-06-02

到目前为止, 我们的API并未指明哪些人有权限编辑或删除snippet, 接下来我们要实现:

  • 为snippet增加创建者
  • 特定用户才能创建snippet
  • snippet创建者才能更新或删除该snippet
  • 未授权用户只能查看

1. 为snippet model增加field

我们现为snippet model增加两个field, 一个用于储存创建者信息, 另一个则用作储存高亮HTML信息:

    # snippets/models.py
from django.db import models
from pygments.lexers import get_all_lexers
from pygments.styles import get_all_styles LEXERS = [item for item in get_all_lexers() if item[1]]
LANGUAGE_CHOICES = sorted([(item[1][0], item[0]) for item in LEXERS])
STYLE_CHOICES = sorted((item, item) for item in get_all_styles()) class Snippet(models.Model):
created = models.DateTimeField(auto_now_add=True)
title = models.CharField(max_length=100, blank=True, default='')
code = models.TextField()
linenos = models.BooleanField(default=False)
language = models.CharField(choices=LANGUAGE_CHOICES,
default='python',
max_length=100)
style = models.CharField(choices=STYLE_CHOICES,
default='friendly',
max_length=100)
owner = models.ForeignKey('auth.User', related_name='snippets')
highlighted = models.TextField() class Meta:
ordering = ('created',)

当执行save()时, 我们使用pygments生成高亮后的HTML:

    # snippets/models.py
from pygments.lexers import get_lexer_by_name
from pygments.formatters.html import HtmlFormatter
from pygments import highlight class Snippet(models.Model): ... 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)

修改完毕之后我们删除原来的数据库, 然后重新创建数据库:

    python ./manage.py syncdb

你可能需要再创建几个用户, 可以通过以下命令创建:

    python ./manage.py createsuperuser

2. 为User model增加endpoints

在serializer.py中增加UserSerializer:

    # snippets/serializers.py
from django.contrib.auth.models import User class UserSerializer(serializers.ModelSerializer):
snippets = serializers.PrimaryKeyRelatedField(many=True) class Meta:
model = User
fields = ('id', 'username', 'snippets')

由于"snippets"是User的一个反向关系, 因此我们需要用field明确指明.

我们只需要为user model添加只读的API, 因此使用ListAPIView和RetrieveAPIView即可:

    # 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

最后修改urls.py, 添加users:

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

3. 关联user和snippet

如果现在我们通过API创建snippet, 我们无法将创建者将其关联起来. 因为创建者信息并不是以serialized数据传进来的, 而是通过request获取的.

我们的解决方法是重写SnippetList和SnippetDetail view的pre_save()方法. 该方法允许我们处理request或request URL中的任何信息.

    # snippets/views.py
class SnippetList(APIView): ... def pre_save(self, obj):
obj.owner = self.request.user class SnippetDetail(APIView): ... def pre_save(self, obj):
obj.owner = self.request.user

4. 更新 serializer

现在snippet已经与创建者关联, 接下来我们修改serializer来反映该变化:

# snippets/serializers.py
class SnippetSerializer(serializers.ModelSerializer):
owner = serializers.Field(source='owner.username') class Meta:
model = Snippet
fields = ('id', 'title', 'code', 'linenos', 'language', 'style', 'owner')

ower field十分有趣, source参数控制着使用snippet哪个attribute作为来源填充该field, 并且能使用"."语法.

Field类, 相对于其他field类(CharField, BooleanField等), 是只读field. 它能用作呈现序列化的数据, 但不会在凡序列化时被用做更新数据.

5. 添加权限

到此为止, snippet已经与user关联了. 接下来我们实现只有授权用户才能创建, 更新和删除snippet.

Django REST Framework为我们提供了许多permission类. 在此, 我们使用IsAuthenticatedOrReadOnly, 它能保证只有授权用户才有读写权限, 而一般用户只有读得权限:

    # snippets/views.py
from rest_framework import permissions
class SnippetList(APIView): ... permission_classes = (permissions.IsAuthenticatedOrReadOnly,) class SnippetDetail(APIView): ... permission_classes = (permissions.IsAuthenticatedOrReadOnly,)

6. 增加可浏览的授权API

在tutorial/urls.py中:

    # 在tutorial/urls.py

    urlpatterns = patterns('',
...
) urlpatterns += patterns('',
url(r'^api-auth/', include('rest_framework.urls',
namespace='rest_framework')),
)

r'^api-auth/'可以是你能想得到的所有pattern. 到此你可以使用/api-auth/进行登录了. 登录成功之后你才能创建snippet.

添加好snippet之后, 在浏览/users/ endpoint, 你可以发现每个用户下都有对应的snippet的pk.

7. 添加对象权限

接下来, 我们实现只有snippet的创建者才能更新, 编辑或删除snippet, 创建snippets/permissions.py:

    # snippets/permissions.py
from rest_framework import permissions class IsOwnerOrReadOnly(permissions.BasePermission):
"""
允许创建者编辑的自定义权限
""" def has_object_permission(self, request, view, obj):
# 任何request都有只读权限, 所以总是允许GET, HEAD 或 OPTIONS
if request.method in permissions.SAFE_METHODS:
return True # 只有snippet的创建者有写的权限
return obj.owner == request.user

修改SnippetDetail view:

    # snippets/views.py
from snippets.permissions import IsOwnerOrReadOnly class SnippetDetail(APIView): ... permission_classes = (permissions.IsAuthenticatedOrReadOnly,
IsOwnerOrReadOnly,)

8. 使用API授权

目前为止, 我们没有设置 authentication classes, 因此 authentication classes 还是默认的SessionAuthentication和BasicAuthentication.

当我们使用浏览器时, 我们可以通过浏览器登录并使用session授权接下来的request.

但当我们使用程序调用API时, 我们必须为每次request提供授权信息:

    curl -X POST http://127.0.0.1:8000/snippets/ -d "code=print 789" -u tom:password

    {"id": 5, "owner": "tom", "title": "foo", "code": "print 789", "linenos": false, "language": "python", "style": "friendly"}

原文链接: http://www.weiguda.com/blog/22/

django rest framework的更多相关文章

  1. 使用django rest framework

    django 刚接触,想做一些restful api , google了一下,发现有现成的框架.Django REST framework. 对使用做下记录: 安装 从http://django-re ...

  2. 利用 Django REST framework 编写 RESTful API

    利用 Django REST framework 编写 RESTful API Updateat 2015/12/3: 增加 filter 最近在玩 Django,不得不说 rest_framewor ...

  3. django rest framework 入门

    django rest framework 入门1-序列化 Serialization 分类: Python 2013-01-22 22:24 11528人阅读 评论(0) 收藏 举报 djangop ...

  4. django rest framework csrf failed csrf token missing or incorrect

    django rest framework csrf failed csrf token missing or incorrect REST_FRAMEWORK = { 'DEFAULT_AUTHEN ...

  5. Django REST Framework学习——Android使用REST方法访问Diango

    本文更应该叫做Android如何模拟浏览器访问Django服务器后台. 环境为: Android通过HttpClient访问服务器,从Django中获取json数据,解析显示在UI界面上. 问题为: ...

  6. 用Django Rest Framework和AngularJS开始你的项目

    Reference: http://blog.csdn.net/seele52/article/details/14105445 译序:虽然本文号称是"hello world式的教程&quo ...

  7. Django REST framework使用ViewSets的自定义路由实现过程

    在Django中使用基于类的视图(ClassView),类中所定义的方法名称与Http的请求方法相对应,才能基于路由将请求分发(dispatch)到ClassView中的方法进行处理,而Django ...

  8. Django REST FrameWork中文教程2:请求和响应

    从这一点开始,我们将真正开始覆盖REST框架的核心.我们来介绍几个基本的构建块. 请求对象REST框架引入了Request扩展常规的对象HttpRequest,并提供更灵活的请求解析.Request对 ...

  9. Django REST framework 中文教程1:序列化

    建立环境 在我们做任何事情之前,我们将使用virtualenv创建一个新的虚拟环境.这将确保我们的包配置与我们正在开展的任何其他项目保持良好的隔离. virtualenv envsource env/ ...

随机推荐

  1. Android视频播放之VideoView

    Android视频播放之VideoView 1.VideoView类介绍 Android的VideoView组件可以从不同的来源(例如资源文件或内容提供器)读取图像,计算和维护视频的画面尺寸以使其适用 ...

  2. 在SSIS 2012中使用CDC(数据变更捕获)

    最新项目稍有空隙,开始研究SQL Server 2012和2014的一些BI特性,参照(Matt)的一个示例,我们开始体验SSIS中的CDC(Change Data Capture,变更数据捕获). ...

  3. sql 重复数据只保留一条

    用SQL语句,删除掉重复项只保留一条在几千条记录里,存在着些相同的记录,如何能用SQL语句,删除掉重复的呢1.查找表中多余的重复记录,重复记录是根据单个字段(peopleId)来判断 select * ...

  4. 如何实现EndNote中的PDF批量导出

    如果在EndNote数据库中已建立大量的参考文献,且每条文献都有PDF文件对应,怎样将需要的某十几条甚至几十条参考文献对应的PDF文件从数据库导出另存在新建的文件夹   1. 按住“Ctrl”键,逐条 ...

  5. 前端程序员应该知道的15个 jQuery 小技巧

    下面这些简单的小技巧能够帮助你玩转jQuery. 返回顶部按钮 预加载图像 检查图像是否加载 自动修复破坏的图像 悬停切换类 禁用输入字段 停止加载链接 切换淡入/幻灯片 简单的手风琴 让两个div高 ...

  6. [Google Guava]学习--缓存cache

    适用性 缓存在很多情况下非常实用.例如,计算或检索一个值的代价很高,并且对同样的输入需要不止一次获取值的时候,就应当考虑使用缓存. Guava Cache与ConcurrentMap很相似,但也不完全 ...

  7. 状态压缩 HDU 3091

    多组数据 n个点m条边 求有几个经过所有的点的环 最好用__int64 #include<stdio.h> #include<algorithm> #include<st ...

  8. 51nod 1422(强行YY)

    1422 沙拉酱前缀 题目来源: CodeForces 基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题  收藏  关注 沙拉酱非常喜欢数字序列.这正是他要弄一个关于 ...

  9. dede使用方法----如何调用最新文章,最热文章,友情链接

    dede如何调用最新文章 {dede:arclist      row='5'       titlelen='50'    orderby ='pubdate'} <li><a h ...

  10. 学习WebSocket(一):Spring WebSocket的简单使用

    1.什么是websocket? WebSocket协议定义了一种web应用的新功能,它实现了服务器端和客户端的全双工通信.全双工通信即通信的双方可以同时发送和接收信息 的信息交互方式.它是继Java ...