Wprowadzenie.
Kolejną ważną rzeczą, którą należy znać, jest poznanie sposobu nadpisywania metod, które są wykonywane przed lub po operacji zapisu/usunięcia rekordu. Dzięki tej funkcjonalności jesteśmy w stanie na przykład przypisać lub nadpisać dane pole określoną wartością, możemy również z tego miejsca wysłać maila potwierdzającego jakąś czynność lub też wykonać inne działanie, które będzie wymagane przez nasze API.
- perform_create(self, serializer)
- perform_update(self, serializer)
- perform_destroy(self, instance)
Informacji o powyższych funkcjach znajdziemy pod tym linkiem.
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.
- Nadpisywanie zachowań metod przed/po operacji zapisu/usuwania.
Nadpisywanie zachowań metod przed/po operacji zapisu/usuwania.
Załóżmy sobie, że mechanizm zwracania książek ma działać w taki sposób, aby data zwrotu była uzupełniana automatycznie po wysłaniu formularza dotyczącego zwrotu książki. W tym celu stwórzmy nowy Serializer, który będzie zawierał tylko jedno pole ‘id’ z modelu Borrow.
class BorrowReturnBookSerializer(serializers.ModelSerializer): class Meta: model = Borrow fields = ['id']
Następnie zaimportujmy nowo napisany serializer oraz jednocześnie zaimportujmy wbudowany moduł odpowiedzialny za działania na czasie i dacie from django.utils import timezone.
from django.db.models import query from django.shortcuts import render from rest_framework import generics, serializers import rest_framework from rest_framework import permissions from .models import Author, Book, Borrow from .serializers import AuthorSerializer, BookSerializer, BorrowSerializer, BorrowReturnBookSerializer # new from rest_framework.permissions import IsAuthenticated, BasePermission, SAFE_METHODS, IsAdminUser, IsAuthenticatedOrReadOnly from rest_framework.exceptions import ValidationError from django.utils import timezone # new
Napiszmy teraz klasę widoku odpowiedzialną za zwracanie książek. Wprowadźmy ograniczenie dostępu tylko dla autoryzowanych osób oraz nadpiszmy klasę put(), w której dodamy filtr, abyśmy mogli tylko zwrócić tylko nasze pozycje. Nowością w tym miejscu jest nadpisanie klasy perform_update(), w której to zamieścimy wyrażenie odpowiedzialne za przypisanie aktualnej daty do pola instancji return_date serializera BorrowReturnBookSerializer. Następnie musimy pamiętać o koniecznym wywołaniu metody zapisu save().
# new class BorrowReturnBookUpdate(generics.UpdateAPIView): queryset = Borrow.objects.all() serializer_class = BorrowReturnBookSerializer permission_class = [IsAuthenticated] def put(self, request, *args, **kwargs): borrow = Borrow.objects.filter(pk=kwargs['pk'], user_id=self.request.user) if borrow.exists(): return self.update(request, *args, **kwargs) else: raise ValidationError('You are not the owner') def perform_update(self, serializer): serializer.instance.return_date = timezone.now() serializer.save()
Na koniec napiszmy ścieżkę do widoku nowo stworzonej klasy path(‘api/borrows//return/’, views.BorrowReturnBookUpdate.as_view()).
from django.contrib import admin from django.urls import path, include from restapiapp import views urlpatterns = [ path('admin/', admin.site.urls), # API path('api/authors/', views.AuthorList.as_view()), path('api/books/', views.BookList.as_view()), path('api/borrows/', views.BorrowList.as_view()), path('api/borrows/<int:pk>/', views.BorrowRetrieveDestroy.as_view()), path('api/borrows/<int:pk>/return/', views.BorrowReturnBookUpdate.as_view()), # new path('api/borrows/<int:pk>/edit/', views.BorrowRetrieveUpdate.as_view()), # DRF path('api-auth/', include('rest_framework.urls')), ]
W tym momencie możemy przejść do przeprowadzenia testów funkcji zwrotu książek. W tym celu wprowadźmy do przeglądarki adres 127.0.0.1:8000/api/borrows/.
Załóżmy, że chcemy oddać pozycję o id 11, wówczas w przeglądarce musimy wprowadzić adres 127.0.0.1:8000/api/borrows/11/return/.
Jak widźmy w miejscu formularza znajduje się jedynie przycisk PUT, który jest odpowiedzialny za wysłanie formularza metodą PUT.
Po wysłaniu formularza otrzymamy dane zwrotne z numerem id, na której została wykonana metoda PUT. Następnie wprowadźmy adres z listą wypożyczeń.
Jak widzimy data zwrotu do pozycji z id 11, została wprowadzona automatycznie.
W tym miejscu możemy jeszcze sprawdzić, czy czasem nie możemy zwrócić książki, która nie należy do nas.
Wybierzmy teraz pozycję o id 2 i naciśnijmy przycisk PUT.
Jak możemy zobaczyć, otrzymaliśmy informację zwrotną, że nie jesteśmy właścicielami tego wypożyczenia. Dla pewności przejdźmy jeszcze do listy wypożyczeń.
Jak widzimy, data zwrotu nadal ma wartość null.
Na koniec możemy jeszcze wrócić do serializera odpowiedzialnego za wypożyczenie, gdzie wprowadźmy dla porządku, abyśmy nie mogli wpisywać daty zwrotu.
class BorrowSerializer(serializers.ModelSerializer): book = serializers.ReadOnlyField(source='book_id.title') author_first_name = serializers.ReadOnlyField(source='book_id.author_id.first_name') author_last_name = serializers.ReadOnlyField(source='book_id.author_id.last_name') user_firts_name = serializers.ReadOnlyField(source='user_id.first_name') user_last_name = serializers.ReadOnlyField(source='user_id.last_name') user_email = serializers.ReadOnlyField(source='user_id.email') user_id = serializers.ReadOnlyField(source='user_id.id') return_date = serializers.ReadOnlyField() # new class Meta: model = Borrow fields = ['id', 'user_id', 'user_firts_name', 'user_last_name', 'user_email', 'book_id', 'book', 'author_first_name', 'author_last_name', 'borrow_date', 'return_date']
Sprawdźmy, czy teraz podczas wypożyczenia nie ma pola z datą zwrotu.
Jak możemy zauważyć, teraz gdy wypożyczamy książkę, mamy jedynie pozycję Book id, która dla przypomnienia wskazuje, którą książkę mamy zamiar wypożyczyć.
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