Django – #29 – REST API cz. 5 – ListCreateAPIView i konfiguracja dostępu

Wprowadzenie.

Przechodząc dalej, warto zapoznać się z funkcjonalnościami kolejnych widoków generycznych oraz ograniczeniem dostępu w zależności od rodzaju konta. W związku z tym we wpisie zaprezentowałem kolejny widok generyczny, którym jest ListCreateAPIView oraz pokazałem, w jaki sposób, można zarządzać dostępem do danych dla określonego widoku.

Zakres artykułu.

  • Zastosowanie widoku ListCreateAPIView
  • Konfiguracja dostępu

Zastosowanie widoku ListCreateAPIView

Znając już widoki generyczne oraz ich teoretyczną funkcjonalność, przejdźmy do zastosowania kolejnego widoku generycznego, którym jest ListCreateAPIView. Modyfikacja naszego API będzie polegała na tym, że zmienimy dziedziczenie w klasie BorrowList. Usuńmy generics.ListAPIView i dodajmy w to miejsce generics.ListCreateAPIView. Jeżeli chcesz przypomnieć sobie, co dostarczają nam te widoki, przejdź do tego wpisu.

from django.shortcuts import render
from rest_framework import generics
from .models import Author, Book, Borrow
from .serializers import AuthorSerializer, BookSerializer, BorrowSerializer

# Create your views here.
class AuthorList(generics.ListAPIView):
    queryset = Author.objects.all()
    serializer_class = AuthorSerializer

class BookList(generics.ListAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

class BorrowList(generics.ListCreateAPIView): # new
    queryset = Borrow.objects.all()
    serializer_class = BorrowSerializer

Sprawdźmy teraz jaki efekt otrzymamy po wprowadzeniu modyfikacji oraz dokonajmy porównania z poprzednią wersją.

Przed wprowadzeniem modyfikacji.

Po wprowadzeniu modyfikacji.

Jak możemy zobaczyć pierwsza różnica, pojawia nam się w miejscu, gdzie mamy dozwolone metody. Po wprowadzeniu modyfikacji widoczna jest dodatkowa metoda POST.

Drugą różnicę, którą możemy zobaczyć, jest pojawienie się na dole strony formularza z polami, które dodaliśmy na etapie tworzenia modelu. Formularz ten jesteśmy w stanie wysłać metodą POST.

Jak się przyjrzymy, widzimy również że mamy możliwość przełączenia się do zakładki “Raw data“, w której znajduje się czysty tekst w formacie json.

Jak widzimy dzięki wprowadzeniu drobnej modyfikacji w widoku, otrzymujemy spore zmiany na dostarczonej przez framework stronie do testowania API

Konfiguracja dostępu

Aktualnie mamy taką sytuację, że każdy użytkownik, a nawet osoba bez konta może wysłać request POST, taka funkcjonalność w naszym API nie jest pożądana, dlatego teraz zajmiemy się ograniczeniem dostępu.

Framework i w tym przypadku dostarcza nam prosty sposób zarządzania dostępem. Dzięki zmiennej permission_classes i to, co do niej przypiszemy, będziemy w stanie na przykład ograniczyć dostęp.

Załóżmy, że na chwilę obecną chcemy pozwolić, aby request ten był tylko dostępny dla autoryzowanych osób w związku w tym, wprowadźmy następującą modyfikację.

from django.shortcuts import render
from rest_framework import generics
from .models import Author, Book, Borrow
from .serializers import AuthorSerializer, BookSerializer, BorrowSerializer
from rest_framework.permissions import IsAuthenticated # new

# Create your views here.
class AuthorList(generics.ListAPIView):
    queryset = Author.objects.all()
    serializer_class = AuthorSerializer

class BookList(generics.ListAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

class BorrowList(generics.ListCreateAPIView):
    queryset = Borrow.objects.all()
    serializer_class = BorrowSerializer
    permission_classes = [IsAuthenticated] # new

Modyfikacja ta spowodowała, że gdy jesteśmy niezalogowani, nie mamy dostępu do tego adresu, przez co, gdy wyślemy request, otrzymamy stosowaną informację w formacie json.

W przypadku, jeżeli zalogujemy się na dowolne konto, wówczas mamy pełny dostęp do danych.

Pójdźmy jeszcze o krok dalej i dla osób zalogowanych ograniczmy prawa jedynie do odczytu, z tym że cały czas chcemy, aby ogólnie metoda POST była dozwolona. W tym przypadku stwórzmy nową klasę, która będzie dziedziczyła po klasie BasePermission. i będzie pozwalała na wykonywanie jedynie tak zwanych bezpiecznych metod (SAFE_METHODS). Bezpieczne metody to metody ‘GET‘, ‘OPTIONS‘ i ‘HEAD‘.

from django.shortcuts import render
from rest_framework import generics
from .models import Author, Book, Borrow
from .serializers import AuthorSerializer, BookSerializer, BorrowSerializer
from rest_framework.permissions import IsAuthenticated, BasePermission, SAFE_METHODS # new

class ReadOnly(BasePermission): # new
    def has_permission(self, request, view): # new
        return request.method in SAFE_METHODS # new

# Create your views here.
class AuthorList(generics.ListAPIView):
    queryset = Author.objects.all()
    serializer_class = AuthorSerializer

class BookList(generics.ListAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

class BorrowList(generics.ListCreateAPIView):
    queryset = Borrow.objects.all()
    serializer_class = BorrowSerializer
    permission_classes = [IsAuthenticated & ReadOnly] # new

Przed wprowadzeniem modyfikacji mamy dostęp do formularza.

Po wprowadzeniu modyfikacji, jak możemy przeczytać, metoda POST jest dozwolona, jednakże formularz już się nie znajduje na stronie.

Wszystko wygląda dobrze, jednakże do końca to nie było naszym celem, ponieważ obecnie nikt nie może wykonywać metody POST, a przecież chcielibyśmy, żeby na przykład admin miał takie prawo. W związku z tym wykonajmy kolejną modyfikację kodu, gdzie przy określaniu praw, zastosujemy operatory logiczne.

from django.shortcuts import render
from rest_framework import generics
from .models import Author, Book, Borrow
from .serializers import AuthorSerializer, BookSerializer, BorrowSerializer
from rest_framework.permissions import IsAuthenticated, BasePermission, SAFE_METHODS, IsAdminUser # new

class ReadOnly(BasePermission):
    def has_permission(self, request, view):
        return request.method in SAFE_METHODS

# Create your views here.
class AuthorList(generics.ListAPIView):
    queryset = Author.objects.all()
    serializer_class = AuthorSerializer

class BookList(generics.ListAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

class BorrowList(generics.ListCreateAPIView):
    queryset = Borrow.objects.all()
    serializer_class = BorrowSerializer
    permission_classes = [(IsAuthenticated & ReadOnly) | IsAdminUser] # new

W tym momencie konto admina ma prawo do requesta wykonywanego metodą POST.

Widok z konta zwykłego.

Widok z konta admina.

Warto zaznaczyć, że wspierane operatory logiczne dla zmiennej permission_classes to  & (and), | (or) oraz ~ (not).

Autor artykułu
Dominik Bednarski

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany.