django rest framework权限管理实战

时间:2022-01-26 16:20:33

前言

本文标题为实战,那么希望你已经搭建好了环境。如果没有,请参考官方文档进行环境搭建:

官方教程

通过学习这个例子,你可以学到:

  1. 如何使用django rest framework去实现RESTful api
  2. 学会如何进行权限控制

希望对rest framework已经有了一定的了解,至少要知道serializers的作用,还有Response等等,基础知识还是要有的。

实战内容

我们实战的内容是,搭建一个博客应用,提供注册,登录功能。

所有用户都可以发表博客。

实现博客的创建者可以对自己的博客进行修改,删除等操作。

非创建者只能进行浏览。

思路

在登录的时候,将用户的id保存到request.session中,当用户修改博客或者是删除博客的时候,进行比对。所以权限管理主要是permissions.py这个文件的编写,之后再在views.py中进行设置权限即可。

开始

  1. 新建一个project:

    django-admin.py startproject rest

  2. 新建一个app:

    python manage startapp blog

  3. 在blog的models中,建立我们需要的model:

    class User(models.Model):
    username = models.CharField(max_length=20,null=False)
    password = models.CharField(max_length=20,null=False)
    name = models.CharField(max_length=10,null=False) #名称

    class Blog(models.Model):
    title = models.CharField(max_length=50,null=False)
    body = models.TextField()
    owner = models.ForeignKey(User) #博客的创建者

    def __str__(self):
    return self.title
  4. 在blog目录下新建一个serializers.py序列化文件:

    from rest_framework import serializers
    from blog.models import *

    class BlogSerializer(serializers.ModelSerializer):
    owner = serializers.ReadOnlyField(source='owner.name') #只读
    class Meta:
    model = Blog
    fields = ('id', 'title', 'body', 'owner')


    #用于注册的时候返回json数据

    class UserRegisterSerializer(serializers.ModelSerializer):
    class Meta:
    model = User
    fields = ('id', 'username', 'name')

    class UserSerializer(serializers.ModelSerializer):
    blog_set = serializers.PrimaryKeyRelatedField(many=True, queryset=Blog.objects.all())
    class Meta:
    model = User
    fields = ('id', 'username', 'blog_set')
  5. 在blog目录下新建一个权限文件:permissions.py
    当用户登录之后,我们会在requests.session中加入用户的id,所以我们用id作为权限判断的依据:


    #coding=utf-8

    from rest_framework import permissions
    class IsOwnerOrReadOnly(permissions.BasePermission):
    def has_permission(self, request, view):
    if request.method in permissions.SAFE_METHODS:
    return True
    return request.session.get('user_id') is not None

    def has_object_permission(self, request, view, blog):
    # 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
    return blog.owner.id == request.session.get('user_id')
  6. 在views.py中,我们加入下列代码:


    # -*- coding: utf-8 -*-

    from __future__ import unicode_literals

    from django.shortcuts import render


    # Create your views here.

    from rest_framework import viewsets
    from rest_framework.permissions import AllowAny
    from rest_framework.response import Response
    from rest_framework.status import HTTP_200_OK, HTTP_400_BAD_REQUEST
    from rest_framework.views import APIView

    from blog.permissions import IsOwnerOrReadOnly
    from blog.serializers import *


    #用于登录

    class UserLoginAPIView(APIView):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    permission_classes = (AllowAny,)

    def post(self, request, format=None):
    data = request.data
    username = data.get('username')
    password = data.get('password')
    user = User.objects.get(username__exact=username)
    if user.password == password:
    serializer = UserSerializer(user)
    new_data = serializer.data
    # 记忆已登录用户
    self.request.session['user_id'] = user.id
    return Response(new_data, status=HTTP_200_OK)
    return Response('password error', HTTP_400_BAD_REQUEST)


    #用于注册

    class UserRegisterAPIView(APIView):
    queryset = User.objects.all()
    serializer_class = UserRegisterSerializer
    permission_classes = (AllowAny,)

    def post(self, request, format=None):
    data = request.data
    username = data
    if User.objects.filter(username__exact=username):
    return Response("用户名已存在",HTTP_400_BAD_REQUEST)
    serializer = UserRegisterSerializer(data=data)
    if serializer.is_valid(raise_exception=True):
    serializer.save()
    return Response(serializer.data,status=HTTP_200_OK)
    return Response(serializer.errors, status=HTTP_400_BAD_REQUEST)


    #用于博客的增删改查 除了查看,其他都需要权限

    class BlogViewSet(viewsets.ModelViewSet):
    queryset = Blog.objects.all()
    serializer_class = BlogSerializer
    permission_classes = (IsOwnerOrReadOnly)

    def perform_create(self, serializer):
    print self.request.user
    serializer.save(owner=User.objects.get(id=self.request.session.get('user_id')))

    class UserViewSet(viewsets.ModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer

    这样,我们就实现了权限的控制,如果查看博客,那么不会有什么问题。如果要提交博客,或者是删除博客,都是需要用户登录的,而且删除需要用户本人。没有权限则会返回{"detail": "Authentication credentials were not provided."}

  7. 在rest的urls.py中,我们为我们的view设置路由:

    from django.conf.urls import url,include
    from django.contrib import admin
    from rest_framework import routers
    from blog.views import *
    router = routers.DefaultRouter()
    router.register(r'users',UserViewSet)
    router.register(r'blogs',BlogViewSet)

    urlpatterns = [
    url(r'^',include(router.urls)),
    url(r'^admin/', admin.site.urls),
    url(r'^register',UserRegisterAPIView.as_view()),
    url(r'^login',UserLoginAPIView.as_view()),
    ]
  8. 在settings.py中,加入一些代码:

    INSTALLED_APPS = [
    ...
    ...
    'rest_framework',#rest框架
    'blog',#我们的app
    ]

    #add to your settings.py

    REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': [
    'rest_framework.permissions.AllowAny',
    ],
    'PAGE_SIZE': 10
    }
  9. 建立数据库

python manage makemigrations

python manage migrate

到此为止,就全部完成了,接下来可以访问API了!

使用

为了方便提交json数据,我使用了一款名叫Postman的工具,是GoogleChrome的一款插件,建议你也安装一个。如果你不想安装,那么你可以使用命令行的httpie工具,安装:

$ pip install --upgrade pip setuptools

$ pip install --upgrade httpie
  1. 注册一个用户,向http://127.0.0.1:8000/register提交一个post请求,参数如图:
    django rest framework权限管理实战

    对应的httpie命令:

    http --json POST http://127.0.0.1:8000/register username="ICELEE" password="mypass" name="icelee"

    返回结果如下:

    {
    "id": 3,
    "username": "ICELEE",
    "password": "mypass",
    "name": "ICE"
    }

    因为我已经注册了两个了,所以id为3

  2. 先不登录,直接提交一篇博客:
    django rest framework权限管理实战
    对应httpie的命令:

    http --json POST http://127.0.0.1:8000/blogs/ title="第一篇博客" body="哎哟 不错哦"

    结果是:

    {
    "detail": "Authentication credentials were not provided."
    }
  3. 登录:
    django rest framework权限管理实战

    对应的httpie命令:
    http --json POST http://127.0.0.1:8000/login/ username="ICELEE" password="mypass"

    返回的结果:

    {
    "id": 3,
    "blog_set": [],
    "username": "ICELEE",
    "password": "mypass",
    "name": "ICE"
    }
  4. 像第2点一样,再次提交博客,返回结果:

    {
    "id": 5,
    "title": "ICELEE的博客",
    "body": "哎哟 不错哦",
    "owner": "ICE"
    }

你可以再创建一个用户,然后登录,试着删除上面的博客试试,估计你是没办法删除的,因为你不是博客的拥有者,这就是权限控制的作用啦~~~

有疑问的地方请留言给我。
github项目地址