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.
Spis treści serii
- Django REST API cz. 1– Tworzenie nowego projektu
- Django REST API cz. 2 – ListAPIView
- Django REST API cz. 3 – Wbudowana strona logowania
- Django REST API cz. 4 – Widoki generyczne
- Django REST API cz. 5 – ListCreateAPIView i konfiguracja dostępu ⇐
- Django REST API cz. 6 – Uszczegóławianie odpowiedzi
- Django REST API cz. 7 – Określenie z góry wartości danych
- Django REST API cz. 8 – RetrieveDestroyAPIView
- Django REST API cz. 9 – RetrieveUpdateAPIView
- Django REST API cz. 10 – Nadpisywanie zachowań metod przed/po operacji zapisu/usuwania
- Django REST API cz. 11 – Rejestracja nowego użytkownika poprzez API
- Django REST API cz. 12 – Uwierzytelnianie przy pomocy Tokena
- Django REST API cz. 13 – Generowanie tokena dla istniejących użytkowników
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).
Spis treści serii
- Django REST API cz. 1– Tworzenie nowego projektu
- Django REST API cz. 2 – ListAPIView
- Django REST API cz. 3 – Wbudowana strona logowania
- Django REST API cz. 4 – Widoki generyczne
- Django REST API cz. 5 – ListCreateAPIView i konfiguracja dostępu ⇐
- Django REST API cz. 6 – Uszczegóławianie odpowiedzi
- Django REST API cz. 7 – Określenie z góry wartości danych
- Django REST API cz. 8 – RetrieveDestroyAPIView
- Django REST API cz. 9 – RetrieveUpdateAPIView
- Django REST API cz. 10 – Nadpisywanie zachowań metod przed/po operacji zapisu/usuwania
- Django REST API cz. 11 – Rejestracja nowego użytkownika poprzez API
- Django REST API cz. 12 – Uwierzytelnianie przy pomocy Tokena
- Django REST API cz. 13 – Generowanie tokena dla istniejących użytkowników