diff --git a/.gitignore b/.gitignore index 6394a79..4e5619c 100644 --- a/.gitignore +++ b/.gitignore @@ -207,3 +207,6 @@ marimo/_lsp/ __marimo__/ media/ + +logs/ +*.log diff --git a/backend/api/v1/views.py b/backend/api/v1/views.py index b9a8b7f..1a6e8f1 100644 --- a/backend/api/v1/views.py +++ b/backend/api/v1/views.py @@ -1,6 +1,8 @@ +import logging + from django_filters.rest_framework import DjangoFilterBackend from drf_spectacular.utils import extend_schema -from rest_framework import filters, permissions, viewsets +from rest_framework import filters, permissions, serializers, viewsets from api.v1.permissions import IsAdminOrReadOnly, IsOwnerOrAdmin from api.v1.serializers import ( @@ -14,6 +16,8 @@ ) from rooms.models import Booking, Room, RoomImage, RoomType +logger = logging.getLogger("rooms") + @extend_schema(tags=["RoomType"], summary="Управление типами номеров") class RoomTypeViewSet(viewsets.ModelViewSet): @@ -28,6 +32,15 @@ class RoomTypeViewSet(viewsets.ModelViewSet): filter_backends = (filters.OrderingFilter,) ordering_fields = ("name",) + def get_queryset(self): + try: + queryset = RoomType.objects.all() + logger.info(f"Запрошены типы номеров, всего найдено: {queryset.count()}") + return queryset + except Exception as error: + logger.debug(f"Ошибка при получении типов номеров: {error}", exc_info=True) + return RoomType.objects.none() + @extend_schema(tags=["RoomImage"]) class RoomImageViewSet(viewsets.ModelViewSet): @@ -36,9 +49,21 @@ class RoomImageViewSet(viewsets.ModelViewSet): permission_classes = (permissions.IsAdminUser,) def get_serializer_class(self): - if self.action in ["list", "retrieve"]: - return RoomImageReadSerializer - return RoomImageWriteSerializer + try: + if self.action in ["list", "retrieve"]: + logger.debug( + f"Используется RoomImageReadSerializer для действия {self.action}" + ) + return RoomImageReadSerializer + logger.debug( + f"Используется RoomImageWriteSerializer для действия {self.action}" + ) + return RoomImageWriteSerializer + except Exception as error: + logger.error( + f"Ошибка при выборе сериализатора для RoomImage: {error}", exc_info=True + ) + return RoomImageWriteSerializer @extend_schema( @@ -66,14 +91,31 @@ class RoomViewSet(viewsets.ModelViewSet): ) def get_serializer_class(self): - if self.action in ["list", "retrieve"]: - return RoomReadSerializer - return RoomWriteSerializer + try: + if self.action in ["list", "retrieve"]: + logger.debug( + f"Используется RoomReadSerializer для действия {self.action}" + ) + return RoomReadSerializer + logger.debug(f"Используется RoomWriteSerializer для действия {self.action}") + return RoomWriteSerializer + except Exception as error: + logger.error( + f"Ошибка при выборе сериализатора для Room: {error}", exc_info=True + ) + return RoomWriteSerializer def get_queryset(self): - if self.request.user.is_staff or self.request.user.is_superuser: - return Room.objects.all() - return Room.objects.filter(is_available=True) + try: + if self.request.user.is_staff or self.request.user.is_superuser: + queryset = Room.objects.all() + else: + queryset = Room.objects.filter(is_available=True) + logger.debug(f"Запрошены номера, всего найдено: {queryset.count()}") + return queryset + except Exception as error: + logger.error(f"Ошибка при получении списка номеров: {error}", exc_info=True) + return Room.objects.none() @extend_schema(tags=["Booking"], summary="Работа с бронированиями") @@ -92,14 +134,46 @@ class BookingViewSet(viewsets.ModelViewSet): ordering_fields = ("status", "check_in", "check_out") def get_serializer_class(self): - if self.action in ["list", "retrieve"]: - return BookingReadSerializer - return BookingWriteSerializer + try: + if self.action in ["list", "retrieve"]: + logger.debug( + f"Используется BookingReadSerializer для действия {self.action}" + ) + return BookingReadSerializer + logger.debug( + f"Используется BookingWriteSerializer для действия {self.action}" + ) + return BookingWriteSerializer + except Exception as error: + logger.error( + f"Ошибка при выборе сериализатора для Booking: {error}", exc_info=True + ) + return BookingWriteSerializer def get_queryset(self): - if self.request.user.is_staff or self.request.user.is_superuser: - return Booking.objects.all() - return Booking.objects.filter(user=self.request.user) + try: + if self.request.user.is_staff or self.request.user.is_superuser: + queryset = Booking.objects.all() + else: + queryset = Booking.objects.filter(user=self.request.user) + logger.debug( + f"Запрошены бронирования пользователем: {self.request.user}, найдеено бронирований: {queryset.count()}" + ) + return queryset + except Exception as error: + logger.error( + f"Ошибка при получении списка бронирований: {error}", exc_info=True + ) + return Booking.objects.none() def perform_create(self, serializer): - serializer.save(user=self.request.user) + try: + serializer.save(user=self.request.user) + logger.info( + f"Пользователь {self.request.user} создал бронирование для номера {serializer.instance.room}" + ) + except Exception as error: + logger.error(f"Не удалось создать бронирование: {error}", exc_info=True) + raise serializers.ValidationError( + {"error": "Не Удалось создать бронирование"} + ) diff --git a/backend/bookinn/settings.py b/backend/bookinn/settings.py index e5a3913..fac870e 100644 --- a/backend/bookinn/settings.py +++ b/backend/bookinn/settings.py @@ -6,6 +6,41 @@ BASE_DIR = Path(__file__).resolve().parent.parent +LOG_DIR = Path(BASE_DIR / "logs") +LOG_DIR.mkdir(exist_ok=True) + +LOGGING = { + "version": 1, + "disable_existing_loggers": False, + "formatters": { + "verbose": { + "format": "{levelname} {asctime} {module} {message}", + "style": "{", + }, + "simple": { + "format": "{levelname} {message}", + "style": "{", + }, + }, + "handlers": { + "console": { + "level": "DEBUG", + "class": "logging.StreamHandler", + "formatter": "verbose", + }, + "file": { + "level": "INFO", + "class": "logging.FileHandler", + "filename": LOG_DIR / "django.log", + "formatter": "verbose", + }, + }, + "loggers": { + "django": {"handlers": ["console", "file"], "level": "INFO", "propagate": True}, + "rooms": {"handlers": ["console", "file"], "level": "DEBUG", "propagate": False}, + }, +} + load_dotenv() SECRET_KEY = os.getenv("SECRET_KEY", default="supersecretkey") diff --git a/requirements.txt b/requirements.txt index 9d7eacc..e61e612 100644 --- a/requirements.txt +++ b/requirements.txt @@ -14,9 +14,11 @@ djangorestframework_simplejwt==5.5.1 djoser==2.3.3 drf-spectacular==0.29.0 flake8==7.3.0 +flake8-isort==6.1.2 idna==3.11 importlib_metadata==8.7.0 inflection==0.5.1 +isort==6.1.0 jsonschema==4.25.1 jsonschema-specifications==2025.9.1 Markdown==3.9 @@ -27,6 +29,7 @@ packaging==25.0 pathspec==0.12.1 pillow==11.3.0 platformdirs==4.4.0 +psycopg2-binary==2.9.11 pycodestyle==2.14.0 pycparser==2.23 pyflakes==3.4.0