From 0e7b0c425f5db620003337764c64af7fd72d00c8 Mon Sep 17 00:00:00 2001 From: Oleh Skibinskyi Date: Sun, 25 Jan 2026 15:18:15 +0200 Subject: [PATCH 1/5] fix: removed fixture --- fixtures/initial_data.json | 265 ------------------------------------- 1 file changed, 265 deletions(-) delete mode 100644 fixtures/initial_data.json diff --git a/fixtures/initial_data.json b/fixtures/initial_data.json deleted file mode 100644 index 7c7e17e..0000000 --- a/fixtures/initial_data.json +++ /dev/null @@ -1,265 +0,0 @@ -[ - { - "model": "users.user", - "pk": 1, - "fields": { - "password": "pbkdf2_sha256$1200000$vBjfJ5vodjFb8FJturiV0J$rmsxK3EtJUsru6Duw2Ap0uXALUN5pt8x1DzxuhBzKuI=", - "is_superuser": true, - "email": "admin@test.com", - "is_staff": true, - "is_active": true, - "first_name": "Admin", - "last_name": "User", - "date_joined": "2026-01-15T12:00:00Z" - } - }, - { - "model": "users.user", - "pk": 2, - "fields": { - "password": "pbkdf2_sha256$1200000$vBjfJ5vodjFb8FJturiV0J$rmsxK3EtJUsru6Duw2Ap0uXALUN5pt8x1DzxuhBzKuI=", - "is_superuser": false, - "email": "user@test.com", - "is_staff": false, - "is_active": true, - "first_name": "Regular", - "last_name": "Customer", - "date_joined": "2026-01-15T12:05:00Z" - } - }, - { - "model": "library.book", - "pk": 1, - "fields": { - "title": "The Great Gatsby", - "author": "F. Scott Fitzgerald", - "cover": "HARD", - "inventory": 5, - "daily_fee": "1.50" - } - }, - { - "model": "library.book", - "pk": 2, - "fields": { - "title": "1984", - "author": "George Orwell", - "cover": "SOFT", - "inventory": 8, - "daily_fee": "0.99" - } - }, - { - "model": "library.book", - "pk": 3, - "fields": { - "title": "Brave New World", - "author": "Aldous Huxley", - "cover": "SOFT", - "inventory": 3, - "daily_fee": "1.20" - } - }, - { - "model": "library.book", - "pk": 4, - "fields": { - "title": "Fahrenheit 451", - "author": "Ray Bradbury", - "cover": "HARD", - "inventory": 10, - "daily_fee": "1.10" - } - }, - { - "model": "library.book", - "pk": 5, - "fields": { - "title": "Animal Farm", - "author": "George Orwell", - "cover": "SOFT", - "inventory": 12, - "daily_fee": "0.75" - } - }, - { - "model": "library.book", - "pk": 6, - "fields": { "title": "The Hobbit", "author": "J.R.R. Tolkien", "cover": "HARD", "inventory": 15, "daily_fee": "2.00" } - }, - { - "model": "library.book", - "pk": 7, - "fields": { "title": "The Catcher in the Rye", "author": "J.D. Salinger", "cover": "SOFT", "inventory": 4, "daily_fee": "1.30" } - }, - { - "model": "library.book", - "pk": 8, - "fields": { "title": "Lord of the Flies", "author": "William Golding", "cover": "HARD", "inventory": 6, "daily_fee": "1.15" } - }, - { - "model": "library.book", - "pk": 9, - "fields": { "title": "The Alchemist", "author": "Paulo Coelho", "cover": "SOFT", "inventory": 20, "daily_fee": "0.95" } - }, - { - "model": "library.book", - "pk": 10, - "fields": { "title": "Crime and Punishment", "author": "Fyodor Dostoevsky", "cover": "HARD", "inventory": 7, "daily_fee": "1.80" } - }, - { - "model": "library.book", - "pk": 11, - "fields": { "title": "The Stranger", "author": "Albert Camus", "cover": "SOFT", "inventory": 9, "daily_fee": "1.40" } - }, - { - "model": "library.book", - "pk": 12, - "fields": { "title": "Dune", "author": "Frank Herbert", "cover": "HARD", "inventory": 11, "daily_fee": "2.10" } - }, - { - "model": "library.book", - "pk": 13, - "fields": { "title": "The Little Prince", "author": "Antoine de Saint-Exupéry", "cover": "SOFT", "inventory": 25, "daily_fee": "0.50" } - }, - { - "model": "library.book", - "pk": 14, - "fields": { "title": "Moby Dick", "author": "Herman Melville", "cover": "HARD", "inventory": 3, "daily_fee": "1.75" } - }, - { - "model": "library.book", - "pk": 15, - "fields": { "title": "War and Peace", "author": "Leo Tolstoy", "cover": "HARD", "inventory": 5, "daily_fee": "2.50" } - }, - { - "model": "library.book", - "pk": 16, - "fields": { "title": "The Old Man and the Sea", "author": "Ernest Hemingway", "cover": "SOFT", "inventory": 14, "daily_fee": "1.00" } - }, - { - "model": "library.book", - "pk": 17, - "fields": { "title": "To Kill a Mockingbird", "author": "Harper Lee", "cover": "HARD", "inventory": 8, "daily_fee": "1.60" } - }, - { - "model": "library.book", - "pk": 18, - "fields": { "title": "Ulysses", "author": "James Joyce", "cover": "HARD", "inventory": 2, "daily_fee": "3.00" } - }, - { - "model": "library.book", - "pk": 19, - "fields": { "title": "Lolita", "author": "Vladimir Nabokov", "cover": "SOFT", "inventory": 6, "daily_fee": "1.90" } - }, - { - "model": "library.book", - "pk": 20, - "fields": { "title": "The Trial", "author": "Franz Kafka", "cover": "SOFT", "inventory": 9, "daily_fee": "1.45" } - }, - { - "model": "library.book", - "pk": 21, - "fields": { "title": "The Great Hunt", "author": "Robert Jordan", "cover": "HARD", "inventory": 10, "daily_fee": "2.20" } - }, - { - "model": "library.book", - "pk": 22, - "fields": { "title": "Wuthering Heights", "author": "Emily Brontë", "cover": "SOFT", "inventory": 7, "daily_fee": "1.10" } - }, - { - "model": "library.book", - "pk": 23, - "fields": { "title": "Jane Eyre", "author": "Charlotte Brontë", "cover": "HARD", "inventory": 8, "daily_fee": "1.25" } - }, - { - "model": "library.book", - "pk": 24, - "fields": { "title": "Catch-22", "author": "Joseph Heller", "cover": "SOFT", "inventory": 5, "daily_fee": "1.35" } - }, - { - "model": "library.book", - "pk": 25, - "fields": { "title": "Slaughterhouse-Five", "author": "Kurt Vonnegut", "cover": "HARD", "inventory": 4, "daily_fee": "1.55" } - }, - { - "model": "library.book", - "pk": 26, - "fields": { "title": "The Road", "author": "Cormac McCarthy", "cover": "SOFT", "inventory": 11, "daily_fee": "1.65" } - }, - { - "model": "library.book", - "pk": 27, - "fields": { "title": "Beloved", "author": "Toni Morrison", "cover": "HARD", "inventory": 6, "daily_fee": "1.70" } - }, - { - "model": "library.book", - "pk": 28, - "fields": { "title": "The Shining", "author": "Stephen King", "cover": "SOFT", "inventory": 13, "daily_fee": "1.20" } - }, - { - "model": "library.book", - "pk": 29, - "fields": { "title": "Foundation", "author": "Isaac Asimov", "cover": "HARD", "inventory": 9, "daily_fee": "2.05" } - }, - { - "model": "library.book", - "pk": 30, - "fields": { "title": "Dracula", "author": "Bram Stoker", "cover": "SOFT", "inventory": 10, "daily_fee": "0.85" } - }, - { - "model": "library.borrowing", - "pk": 1, - "fields": { - "borrow_date": "2026-01-10", - "expected_return_date": "2026-01-20", - "actual_return_date": null, - "book": 1, - "user": 2 - } - }, - { - "model": "library.borrowing", - "pk": 2, - "fields": { - "borrow_date": "2026-01-12", - "expected_return_date": "2026-01-15", - "actual_return_date": "2026-01-14", - "book": 2, - "user": 2 - } - }, - { - "model": "library.borrowing", - "pk": 3, - "fields": { - "borrow_date": "2026-01-13", - "expected_return_date": "2026-01-23", - "actual_return_date": null, - "book": 5, - "user": 2 - } - }, - { - "model": "library.borrowing", - "pk": 4, - "fields": { - "borrow_date": "2026-01-14", - "expected_return_date": "2026-01-21", - "actual_return_date": null, - "book": 10, - "user": 1 - } - }, - { - "model": "library.borrowing", - "pk": 5, - "fields": { - "borrow_date": "2026-01-15", - "expected_return_date": "2026-01-25", - "actual_return_date": null, - "book": 30, - "user": 2 - } - } -] \ No newline at end of file From ec721b5c6244b9604f5c2921b06c945d85a6ecfc Mon Sep 17 00:00:00 2001 From: Oleh Skibinskyi Date: Sun, 25 Jan 2026 15:25:00 +0200 Subject: [PATCH 2/5] fix: replace tuple to list of class instance on used class in views --- library/views.py | 8 ++++---- payment/views.py | 6 +++--- users/views.py | 10 +++++----- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/library/views.py b/library/views.py index 806d396..0a286c1 100644 --- a/library/views.py +++ b/library/views.py @@ -30,8 +30,8 @@ class BookViewSet( GenericViewSet, ): queryset = Book.objects.all().order_by("id") - serializer_class = BookSerializer - permission_classes = (IsAdminOrReadOnly,) + serializer_class = BookSerializer() + permission_classes = [IsAdminOrReadOnly(),] class BorrowingViewSet( @@ -40,8 +40,8 @@ class BorrowingViewSet( mixins.RetrieveModelMixin, GenericViewSet, ): - permission_classes = (IsAuthenticated,) - filter_backends = (OrderingFilter,) + permission_classes = [IsAuthenticated(),] + filter_backends = [OrderingFilter(),] ordering_fields = ( "borrow_date", "expected_return_date", diff --git a/payment/views.py b/payment/views.py index c2c12db..2e2d6ce 100644 --- a/payment/views.py +++ b/payment/views.py @@ -21,8 +21,8 @@ class PaymentViewSet(ReadOnlyModelViewSet): - serializer_class = PaymentSerializer - permission_classes = (IsAuthenticated, IsOwnerOrStaff) + serializer_class = PaymentSerializer() + permission_classes = [IsAuthenticated(), IsOwnerOrStaff()] def get_queryset(self): user = self.request.user @@ -53,7 +53,7 @@ def payment_cancel(request): @method_decorator(csrf_exempt, name="dispatch") class StripeWebhookView(APIView): - permission_classes = [AllowAny] + permission_classes = [AllowAny()] authentication_classes = [] def post(self, request): diff --git a/users/views.py b/users/views.py index 38b6474..35b9ade 100644 --- a/users/views.py +++ b/users/views.py @@ -15,11 +15,11 @@ ) ) class CreateUserView(generics.CreateAPIView): - serializer_class = UserSerializer + serializer_class = UserSerializer() class LoginUserView(TokenObtainPairView): - renderer_classes = [JSONRenderer, BrowsableAPIRenderer] + renderer_classes = [JSONRenderer(), BrowsableAPIRenderer()] serializer_class = AuthTokenSerializer @@ -33,9 +33,9 @@ class LoginUserView(TokenObtainPairView): ), ) class ManageUserView(generics.RetrieveUpdateAPIView): - serializer_class = UserSerializer - authentication_classes = (JWTAuthentication,) - permission_classes = (IsAuthenticated,) + serializer_class = UserSerializer() + authentication_classes = [JWTAuthentication(),] + permission_classes = [IsAuthenticated()] def get_object(self): return self.request.user From 41db34b31486861ac4fe349fd8fae053e35f5e15 Mon Sep 17 00:00:00 2001 From: Oleh Skibinskyi Date: Sun, 25 Jan 2026 15:28:54 +0200 Subject: [PATCH 3/5] rewrite: resolve black comments --- library/views.py | 12 +++++++++--- users/views.py | 4 +++- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/library/views.py b/library/views.py index 0a286c1..4c35fd1 100644 --- a/library/views.py +++ b/library/views.py @@ -31,7 +31,9 @@ class BookViewSet( ): queryset = Book.objects.all().order_by("id") serializer_class = BookSerializer() - permission_classes = [IsAdminOrReadOnly(),] + permission_classes = [ + IsAdminOrReadOnly(), + ] class BorrowingViewSet( @@ -40,8 +42,12 @@ class BorrowingViewSet( mixins.RetrieveModelMixin, GenericViewSet, ): - permission_classes = [IsAuthenticated(),] - filter_backends = [OrderingFilter(),] + permission_classes = [ + IsAuthenticated(), + ] + filter_backends = [ + OrderingFilter(), + ] ordering_fields = ( "borrow_date", "expected_return_date", diff --git a/users/views.py b/users/views.py index 35b9ade..211b887 100644 --- a/users/views.py +++ b/users/views.py @@ -34,7 +34,9 @@ class LoginUserView(TokenObtainPairView): ) class ManageUserView(generics.RetrieveUpdateAPIView): serializer_class = UserSerializer() - authentication_classes = [JWTAuthentication(),] + authentication_classes = [ + JWTAuthentication(), + ] permission_classes = [IsAuthenticated()] def get_object(self): From 6a4a9094e2389a2bd8e796ce9f5440f330c4b12d Mon Sep 17 00:00:00 2001 From: Oleh Skibinskyi Date: Sun, 25 Jan 2026 15:33:31 +0200 Subject: [PATCH 4/5] fix: replace tuple to list in get_permissions function at library/view.py --- library/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/views.py b/library/views.py index 4c35fd1..4c26a08 100644 --- a/library/views.py +++ b/library/views.py @@ -86,7 +86,7 @@ def get_serializer_class(self): def get_permissions(self): if self.action in ("retrieve", "return_book"): - return (IsAuthenticated(), IsOwnerOrStaff()) + return [IsAuthenticated(), IsOwnerOrStaff()] return super().get_permissions() @transaction.atomic From c4539c3876af97286cbd8bfe1d4c3ce702f609c4 Mon Sep 17 00:00:00 2001 From: Oleh Skibinskyi Date: Sun, 25 Jan 2026 15:39:32 +0200 Subject: [PATCH 5/5] fix: replaced class instances to class link --- library/views.py | 10 +++++----- payment/views.py | 6 +++--- users/views.py | 10 +++++----- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/library/views.py b/library/views.py index 4c26a08..b4db5e5 100644 --- a/library/views.py +++ b/library/views.py @@ -30,9 +30,9 @@ class BookViewSet( GenericViewSet, ): queryset = Book.objects.all().order_by("id") - serializer_class = BookSerializer() + serializer_class = BookSerializer permission_classes = [ - IsAdminOrReadOnly(), + IsAdminOrReadOnly, ] @@ -43,10 +43,10 @@ class BorrowingViewSet( GenericViewSet, ): permission_classes = [ - IsAuthenticated(), + IsAuthenticated, ] filter_backends = [ - OrderingFilter(), + OrderingFilter, ] ordering_fields = ( "borrow_date", @@ -86,7 +86,7 @@ def get_serializer_class(self): def get_permissions(self): if self.action in ("retrieve", "return_book"): - return [IsAuthenticated(), IsOwnerOrStaff()] + return [IsAuthenticated, IsOwnerOrStaff] return super().get_permissions() @transaction.atomic diff --git a/payment/views.py b/payment/views.py index 2e2d6ce..bc4b59a 100644 --- a/payment/views.py +++ b/payment/views.py @@ -21,8 +21,8 @@ class PaymentViewSet(ReadOnlyModelViewSet): - serializer_class = PaymentSerializer() - permission_classes = [IsAuthenticated(), IsOwnerOrStaff()] + serializer_class = PaymentSerializer + permission_classes = [IsAuthenticated, IsOwnerOrStaff] def get_queryset(self): user = self.request.user @@ -53,7 +53,7 @@ def payment_cancel(request): @method_decorator(csrf_exempt, name="dispatch") class StripeWebhookView(APIView): - permission_classes = [AllowAny()] + permission_classes = [AllowAny] authentication_classes = [] def post(self, request): diff --git a/users/views.py b/users/views.py index 211b887..af1c2b1 100644 --- a/users/views.py +++ b/users/views.py @@ -15,11 +15,11 @@ ) ) class CreateUserView(generics.CreateAPIView): - serializer_class = UserSerializer() + serializer_class = UserSerializer class LoginUserView(TokenObtainPairView): - renderer_classes = [JSONRenderer(), BrowsableAPIRenderer()] + renderer_classes = [JSONRenderer, BrowsableAPIRenderer] serializer_class = AuthTokenSerializer @@ -33,11 +33,11 @@ class LoginUserView(TokenObtainPairView): ), ) class ManageUserView(generics.RetrieveUpdateAPIView): - serializer_class = UserSerializer() + serializer_class = UserSerializer authentication_classes = [ - JWTAuthentication(), + JWTAuthentication, ] - permission_classes = [IsAuthenticated()] + permission_classes = [IsAuthenticated] def get_object(self): return self.request.user