Add an endpoint for borrowing return
I have this tasks for borrowing books in the library:
Implement return Borrowing functionality
- Make sure you cannot return borrowing twice
- Add 1 to book inventory on returning
- Add an endpoint for borrowing books
POST: borrowings//return/ - set actual return date (inventory should be made += 1)
I can not understand how to make a return endpoint.
book/models.py
from django.db import models
class Book(models.Model):
COVER_CHOICES = [("HARD", "Hard cover"), ("SOFT", "Soft cover")]
title = models.CharField(max_length=255)
authors = models.CharField(max_length=256)
cover = models.CharField(max_length=15, choices=COVER_CHOICES)
inventory = models.PositiveIntegerField()
daily_fee = models.DecimalField(max_digits=7, decimal_places=2)
class Meta:
ordering = ["title"]
def __str__(self):
return (
f"'{self.title}' by {self.authors}, "
f"cover: {self.cover}, "
f"daily fee: {self.daily_fee}, "
f"inventory: {self.inventory}"
)
def reduce_inventory_book(self):
self.inventory -= 1
self.save()
def increase_inventory_book(self):
self.inventory += 1
self.save()
borrowing/models.py
from django.conf import settings
from django.contrib.auth.models import AbstractUser
from django.core.exceptions import ValidationError
from django.db import models
from book.models import Book
class Borrowing(models.Model):
borrow_date = models.DateField(auto_now_add=True)
expected_return_date = models.DateField()
actual_return_date = models.DateField(null=True, blank=True)
book = models.ForeignKey(Book, on_delete=models.PROTECT, related_name="borrowings")
user = models.ForeignKey(
settings.AUTH_USER_MODEL, on_delete=models.PROTECT, related_name="borrowings"
)
@staticmethod
def validate_book_inventory(inventory: int, title: str, error_to_raise):
if not (inventory > 0):
raise error_to_raise(
{"book": f"There is currently no book: {title} to borrow"}
)
def clean(self):
Borrowing.validate_book_inventory(
self.book.inventory, self.book.title, ValidationError
)
def save(
self, force_insert=False, force_update=False, using=None, update_fields=None
):
if not self.actual_return_date:
self.full_clean()
self.book.reduce_inventory_book()
return super(Borrowing, self).save(
force_insert, force_update, using, update_fields
)
self.book.increase_inventory_book()
return super(Borrowing, self).save(
force_insert, force_update, using, update_fields
)
borrowing/views.py
from rest_framework import viewsets
from borrowing.models import Borrowing
from borrowing.serializers import BorrowingSerializer
class BorrowingViewSet(viewsets.ModelViewSet):
queryset = Borrowing.objects.all()
serializer_class = BorrowingSerializer
def get_queryset(self):
queryset = self.queryset
if not self.request.user.is_staff:
queryset = queryset.filter(user=self.request.user)
user_id = self.request.query_params.get("user_id")
is_active = self.request.query_params.get("is_active")
if str(self.request.user.id) == user_id and is_active:
queryset = queryset.filter(actual_return_date=None)
return queryset
def perform_create(self, serializer):
serializer.save(user=self.request.user)
borrowing/serializers.py
from rest_framework import serializers
from borrowing.models import Borrowing
class BorrowingSerializer(serializers.ModelSerializer):
def validate(self, attrs):
data = super(BorrowingSerializer, self).validate(attrs)
if not attrs["actual_return_date"]:
Borrowing.validate_book_inventory(
attrs["book"].inventory,
attrs["book"].title,
serializers.ValidationError,
)
return data
class Meta:
model = Borrowing
fields = (
"id",
"borrow_date",
"expected_return_date",
"actual_return_date",
"book",
)
borrowing/urls.py
from django.urls import path, include
from rest_framework import routers
from borrowing.views import BorrowingViewSet
app_name = "borrowing"
router = routers.DefaultRouter()
router.register("borrowings", BorrowingViewSet)
urlpatterns = [
path("", include(router.urls)),
]
I can not understand how to make a return endpoint. I tried to do something like this https://www.django-rest-framework.org/tutorial/6-viewsets-and-routers/ but it didn't work