django rest framework権限管理実戦

7919 ワード

前言
本文のタイトルは実戦で、それではあなたがすでに環境を構築したことを望んでいます.ない場合は、公式ドキュメントを参照して環境構築を行います.
公式チュートリアル
この例を学ぶことで、次のことを学ぶことができます.
  • django rest frameworkでRESTful apiを実現する方法
  • 権限制御の習得
  • rest frameworkに対してすでに一定の理解があることを望んで、少なくともserializersの作用を知っていて、Responseなどがあって、基礎知識はやはりあります.
    実戦内容
    私たちの実戦の内容は、ブログアプリケーションを構築し、登録、ログイン機能を提供することです.
    すべてのユーザーがブログを発表できます.
    ブログを実現する作成者は、自分のブログを修正したり、削除したりすることができます.
    非作成者はブラウズのみ可能です.##構想はログイン時にユーザのidをrequestに保存する.セッションでは,ユーザがブログを修正したり削除したりした場合に比較する.だから権限管理は主にpermissionsです.pyこのファイルの作成はviewsで行います.pyで権限を設定すればいいです.
    スタート
  • 新規プロジェクト:django-admin.py startproject rest
  • 新しいapp:python manage startapp blog
  • 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
    
  • 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','password', 'name')
    
    class UserSerializer(serializers.ModelSerializer):
        blog_set = serializers.PrimaryKeyRelatedField(many=True, queryset=Blog.objects.all())
        class Meta:
            model = User
            fields = ('id', 'username', 'blog_set')
    
  • blogディレクトリの下に権限ファイルを新規作成する:permissions.pyユーザーがログインするとrequestsにいます.セッションにユーザの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')
    
  • 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.get('username')
            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."}
  • 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()),
    ]
    
  • 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
    }
    
  • データベースの構築
  • 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/registerpostリクエストを送信します.パラメータは図のように:対応する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"
    }
    
    2つ登録したのでidは3
  • 登録せずに、httpie対応命令を直接ブログに提出する:http --json POST http://127.0.0.1:8000/blogs/ title=" " body=" "結果は:
    {
        "detail": "Authentication credentials were not provided."
    }
    
  • 登録:
  • 対応するhttpコマンド:http --json POST http://127.0.0.1:8000/login/ username="ICELEE" password="mypass"返される結果:
    {
        "id": 3,
        "blog_set": [],
        "username": "ICELEE",
        "password": "mypass",
        "name": "ICE"
    }
    
  • 2点目のように再度ブログを提出し、結果を返す:
    {
        "id": 5,
        "title": "ICELEE   ",
        "body": "      ",
        "owner": "ICE"
    }
    
  • もう一人のユーザーを作成してログインして、上のブログを削除してみてください.削除できないと思います.ブログの所有者ではありませんから、これが権限制御の役割です.~~~~
    質問があったらメッセージをください.githubプロジェクトアドレス