Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ RUN adduser \
RUN pip install --no-cache-dir poetry

COPY pyproject.toml poetry.lock ./
RUN poetry config virtualenvs.create false && poetry install --no-dev --no-interaction
RUN poetry config virtualenvs.create false && poetry install --only main --no-interaction --no-root

USER appuser

Expand Down
3 changes: 3 additions & 0 deletions book/apps.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,6 @@
class BookConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "book"

def ready(self):
import book.signals # noqa
11 changes: 11 additions & 0 deletions book/signals.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from django.core.cache import cache
from django.db.models.signals import post_save, post_delete
from django.dispatch import receiver

from book.models import Book


@receiver([post_save, post_delete], sender=Book)
def invalidate_cache(sender, instance, **kwargs):
cache.delete_pattern("*book_view*")
cache.delete_pattern("*borrowing_view*")
4 changes: 4 additions & 0 deletions book/tests/test_book_view_set.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from django.contrib.auth import get_user_model
from django.core.cache import cache
from rest_framework import status
from rest_framework.test import APITestCase
from book.models import Book
Expand Down Expand Up @@ -27,6 +28,9 @@ def setUp(self):
email="user@example.com", password="user123"
)

def tearDown(self):
cache.clear()

def test_list_books_unauthenticated(self):
"""Test: Unauthenticated users can view the list of books"""
response = self.client.get("/api/books/")
Expand Down
13 changes: 13 additions & 0 deletions book/views.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from django.utils.decorators import method_decorator
from django.views.decorators.cache import cache_page
from rest_framework import viewsets

from book.models import Book
Expand All @@ -17,3 +19,14 @@ class BookViewSet(viewsets.ModelViewSet):
permission_classes = [
IsAdminOrReadOnly,
]

@method_decorator(cache_page(60 * 5, key_prefix="book_view"))
def dispatch(self, request, *args, **kwargs):
"""
Method to dispatch the request, with caching applied
for the crew view.

The response is cached for 5 minutes using the
key prefix 'book_view'.
"""
return super().dispatch(request, *args, **kwargs)
7 changes: 6 additions & 1 deletion borrowing/signals.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from django.db.models.signals import post_save
from django.core.cache import cache
from django.db.models.signals import post_save, post_delete
from django.dispatch import receiver
from .models import Borrowing
from tg_bot.utils import send_telegram_notification
Expand All @@ -25,3 +26,7 @@ def handle_borrowing_creation(instance, created, **kwargs):
f" Expected return date: {instance.expected_return_date}"
)
send_telegram_notification.delay(message)

@receiver([post_save, post_delete], sender=Borrowing)
def invalidate_cache(sender, instance, **kwargs):
cache.delete_pattern("*borrowing_view*")
4 changes: 4 additions & 0 deletions borrowing/tests/test_borrowing_api.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from rest_framework.test import APITestCase
from rest_framework import status
from django.urls import reverse
from django.core.cache import cache
from datetime import timedelta
from django.utils.timezone import now
from django.contrib.auth import get_user_model
Expand All @@ -24,6 +25,9 @@ def setUp(self):
)
self.client.force_authenticate(user=self.user)

def tearDown(self):
cache.clear()

def test_create_borrowing_no_inventory(self):
"""Test creating a borrowing record when no copies are available."""
self.book.inventory = 0
Expand Down
13 changes: 13 additions & 0 deletions borrowing/views.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import datetime

from django.utils.decorators import method_decorator
from django.views.decorators.cache import cache_page
from django.http import HttpResponseRedirect
from rest_framework import viewsets, mixins, status
from rest_framework.decorators import action
Expand Down Expand Up @@ -118,3 +120,14 @@ def return_book(self, request, pk=None):
return HttpResponseRedirect(
payment.session_url, status=status.HTTP_302_FOUND
)

@method_decorator(cache_page(60 * 5, key_prefix="borrowing_view"))
def dispatch(self, request, *args, **kwargs):
"""
Method to dispatch the request, with caching applied
for the crew view.

The response is cached for 5 minutes using the
key prefix 'borrowing_view'.
"""
return super().dispatch(request, *args, **kwargs)
21 changes: 21 additions & 0 deletions core/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,26 @@

# Database
# https://docs.djangoproject.com/en/5.1/ref/settings/#databases
if os.environ.get("ENVIRONMENT") == "local":
CACHES = {
'default': {
'BACKEND': 'django_redis.cache.RedisCache',
'LOCATION': 'redis://127.0.0.1:6379/1',
'OPTIONS': {
'CLIENT_CLASS': 'django_redis.client.DefaultClient',
}
}
}
else:
CACHES = {
'default': {
'BACKEND': 'django_redis.cache.RedisCache',
'LOCATION': 'redis://redis:6379/0',
'OPTIONS': {
'CLIENT_CLASS': 'django_redis.client.DefaultClient',
}
}
}

if os.environ.get("ENVIRONMENT") == "local":
DATABASES = {
Expand All @@ -118,6 +138,7 @@
"rest_framework_simplejwt.authentication.JWTAuthentication",
),
"DEFAULT_SCHEMA_CLASS": "drf_spectacular.openapi.AutoSchema",
"DEFAULT_PAGINATION_CLASS": "rest_framework.pagination.LimitOffsetPagination"
}

SIMPLE_JWT = {
Expand Down
21 changes: 19 additions & 2 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ stripe = "^11.4.1"
celery = {extras = ["redis"], version = "^5.4.0"}
python-telegram-bot = "^21.10"
django-celery-beat = "^2.7.0"
django-redis = "^5.4.0"

[build-system]
requires = ["poetry-core"]
Expand Down
Loading