Skip to content
Merged

Dev #31

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
80 commits
Select commit Hold shift + click to select a range
9bbdc74
валидаторы в моделях
dmsnback Oct 30, 2025
d463ac0
валидаторы в сериализаторах
dmsnback Oct 30, 2025
ac29317
Merge pull request #1 from dmsnback/feature/models
dmsnback Oct 30, 2025
13f855b
requirements
dmsnback Oct 30, 2025
7787820
админка
dmsnback Nov 5, 2025
d891764
админка
dmsnback Nov 5, 2025
f1970e4
Merge pull request #2 from dmsnback/feature/admin
dmsnback Nov 5, 2025
4e8aa59
jwt-auth
dmsnback Nov 6, 2025
f4486e9
Merge pull request #3 from dmsnback/feature/jwt_auth
dmsnback Nov 6, 2025
6128b0c
bookings permission
dmsnback Nov 6, 2025
dd19e73
bookings permission
dmsnback Nov 8, 2025
997d70d
Merge pull request #4 from dmsnback/feature/permissions
dmsnback Nov 8, 2025
b5bfe76
fix validate
dmsnback Nov 8, 2025
7f918db
fix is_available
dmsnback Nov 8, 2025
faf3e49
Merge pull request #5 from dmsnback/fix/is_available
dmsnback Nov 8, 2025
c8e15e2
fix is_available
dmsnback Nov 8, 2025
f3f4afe
Merge pull request #6 from dmsnback/fix/is_available
dmsnback Nov 8, 2025
4644dfb
пагинация
dmsnback Nov 9, 2025
2236dff
Merge pull request #7 from dmsnback/feature/pagination
dmsnback Nov 9, 2025
cab1224
throttling
dmsnback Nov 9, 2025
527f344
Merge pull request #8 from dmsnback/feature/throttles
dmsnback Nov 9, 2025
500edf5
filter, searh, ordering
dmsnback Nov 9, 2025
c1466d0
Merge pull request #9 from dmsnback/feature/filter_sort_search
dmsnback Nov 9, 2025
2ba612e
фото для номеров
dmsnback Nov 10, 2025
b286587
Merge pull request #10 from dmsnback/feature/roomimage
dmsnback Nov 10, 2025
68ad8cc
фото для номеров
dmsnback Nov 10, 2025
6303ca9
Merge pull request #11 from dmsnback/feature/roomimage
dmsnback Nov 10, 2025
7e53410
remake/routers
dmsnback Nov 11, 2025
ccee03d
Merge pull request #12 from dmsnback/remake/routers
dmsnback Nov 11, 2025
55fd83e
Delete bookinn directory
dmsnback Nov 11, 2025
7534d24
update для roomserializer
dmsnback Nov 11, 2025
a3fd14c
update в bookingserializer
dmsnback Nov 12, 2025
96d7589
Merge pull request #13 from dmsnback/featere/updateserializer
dmsnback Nov 12, 2025
fbad5d7
Delete backend/media/room_images directory
dmsnback Nov 12, 2025
77c2f9e
gitignore media
dmsnback Nov 12, 2025
c2f836d
total price и total days в бронировании номера
dmsnback Nov 12, 2025
4ac1a71
Merge pull request #14 from dmsnback/feature/totalprice
dmsnback Nov 12, 2025
c89a533
транслит кирилицы при создании имени изображения при загрузке, формат…
dmsnback Nov 12, 2025
517f5cb
Merge pull request #15 from dmsnback/fix/imageroomname
dmsnback Nov 12, 2025
3a537f8
ReadSerializers, Write
dmsnback Nov 13, 2025
55de742
Исправлено is_available default=True
dmsnback Nov 13, 2025
7b1041b
Merge pull request #16 from dmsnback/remake/serializers
dmsnback Nov 13, 2025
393fe5c
is_available при get выводится Доступен, Недоступен вместо True, False
dmsnback Nov 13, 2025
e982728
Merge pull request #17 from dmsnback/remakeis_available
dmsnback Nov 13, 2025
4f2df2e
Документация
dmsnback Nov 13, 2025
6590b17
Документация
dmsnback Nov 13, 2025
f3f4993
Merge pull request #18 from dmsnback/feature/docs
dmsnback Nov 13, 2025
bd52134
,
dmsnback Nov 13, 2025
6b91804
docs swagger
dmsnback Nov 14, 2025
41c1392
Merge pull request #19 from dmsnback/docs
dmsnback Nov 14, 2025
3509e0f
drf_spectacular перенес в api/urls.py
dmsnback Nov 14, 2025
a18c241
Merge pull request #20 from dmsnback/docs
dmsnback Nov 14, 2025
7d73e76
flake8, black, isort
dmsnback Nov 14, 2025
dc7c983
Merge pull request #21 from dmsnback/feature/linters
dmsnback Nov 14, 2025
7ffab0a
test with flake8
dmsnback Nov 15, 2025
ae9546a
test with flake8
dmsnback Nov 15, 2025
2a44b3c
test with flake8
dmsnback Nov 15, 2025
2df3105
test with black isort flake8
dmsnback Nov 15, 2025
08d2bb2
test with black isort flake8
dmsnback Nov 15, 2025
407c3fe
Merge pull request #22 from dmsnback/feature/github_actions
dmsnback Nov 15, 2025
f25e1d5
Badge actions
dmsnback Nov 16, 2025
2fbcb3a
postgresql
dmsnback Nov 16, 2025
e193240
Merge pull request #23 from dmsnback/feature/postgresql
dmsnback Nov 16, 2025
6a8de76
logging, exceptions
dmsnback Nov 16, 2025
e84f6b1
logging, exceptions
dmsnback Nov 16, 2025
aa23455
Merge pull request #24 from dmsnback/featture/logging
dmsnback Nov 16, 2025
c616acd
logging
dmsnback Nov 17, 2025
2031c6d
Merge pull request #25 from dmsnback/feature/logging
dmsnback Nov 17, 2025
5c88a6b
Переделан формат вывода логов
dmsnback Nov 17, 2025
a7d1d52
Merge pull request #26 from dmsnback/feature/logging
dmsnback Nov 17, 2025
d963d06
docker
dmsnback Nov 17, 2025
4d237a3
docker
dmsnback Nov 17, 2025
d4e9c38
docker
dmsnback Nov 17, 2025
1f8eebf
Merge pull request #27 from dmsnback/feature/docker
dmsnback Nov 17, 2025
d62a734
create fixture
dmsnback Nov 18, 2025
c82c336
Merge pull request #28 from dmsnback/feature/fixture
dmsnback Nov 18, 2025
c1b650c
docker compose загружает образ из dokerhub
dmsnback Nov 18, 2025
78423d4
Merge pull request #29 from dmsnback/docker-compose
dmsnback Nov 18, 2025
3d286b2
readme
dmsnback Nov 20, 2025
37fa379
Merge pull request #30 from dmsnback/feature/readme
dmsnback Nov 20, 2025
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
Binary file added .DS_Store
Binary file not shown.
14 changes: 14 additions & 0 deletions .flake8
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[flake8]
max-line-length = 90
extend-ignore = E501, E203, W503
per-file-ignores =
settings*.py:E402,F403,F405
exclude =
.git,
__pycache__,
.tox,
.eggs,
*.egg,
.venv,
venv,
.migrations
33 changes: 33 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: Bookinn workflow

on: [push]

jobs:
lint:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: 3.11

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r ./backend/requirements.txt

- name: Test with black (check only)
run: |
python -m black . --check

- name: Test with flake8-isort (check only)
run: |
python -m isort . --check-only

- name: Test with flake8
run: |
flake8 . --count --statistics --show-source
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -205,3 +205,8 @@ cython_debug/
marimo/_static/
marimo/_lsp/
__marimo__/

media/

logs/
*.log
145 changes: 143 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,143 @@
# bookinn
Сервис бронирования номеров в отеле
<a name="Начало"></a>

## BookInn

API сервис для бронирования номеров

[![BookInn workflow](https://github.com/dmsnback/bookinn/actions/workflows/main.yml/badge.svg)](https://github.com/dmsnback/bookinn/actions/workflows/main.yml)


- [Описание](#Описание)
- [Технологии](#Технологии)
- [Основные ресурсы](#Ресурсы)
- [Шаблон заполнения .env-файла](#Шаблон)
- [Запуск проекта на локальной машине](#Запуск)
- [Автор](#Автор)

<a name="Описание"></a>

### Описание

Сервис — REST API для бронирования номеров в отеле.
Реализован на Django + Django REST Framework, используется Djoser для аутентификации (JWT), drf-spectacular для документации.

```python
Проект адаптирован для использования PostgreSQL и развёртывания в контейнерах Docker.
```

> [Вернуться в начало](#Начало)
<a name="Технологии"></a>

### Технологии

[![Python](https://img.shields.io/badge/python-3670A0?style=for-the-badge&logo=python&logoColor=ffdd54)](https://www.python.org)
![Django](https://img.shields.io/badge/django-%23092E20.svg?style=for-the-badge&logo=django&logoColor=white)
[![DjangoREST](https://img.shields.io/badge/DJANGO-REST-ff1709?style=for-the-badge&logo=django&logoColor=white&color=ff1709&labelColor=gray)](https://www.django-rest-framework.org)
[![Docker](https://img.shields.io/badge/docker-%230db7ed.svg?style=for-the-badge&logo=docker&logoColor=white)](https://www.docker.com)
[![Postgres](https://img.shields.io/badge/postgres-%23316192.svg?style=for-the-badge&logo=postgresql&logoColor=white)](https://www.postgresql.org)
[![GitHub Actions](https://img.shields.io/badge/github%20actions-%232671E5.svg?style=for-the-badge&logo=githubactions&logoColor=white)](https://github.com/features/actions)
[![Nginx](https://img.shields.io/badge/nginx-%23009639.svg?style=for-the-badge&logo=nginx&logoColor=white)](https://nginx.org/ru/)
[![Gunicorn](https://img.shields.io/badge/gunicorn-%298729.svg?style=for-the-badge&logo=gunicorn&logoColor=white)](https://gunicorn.org)

> [Вернуться в начало](#Начало)

<a name="Ресурсы"></a>

### Основные ресурсы

- `/api/v1/rooms/` — CRUD и список номеров
- `/api/v1/room_type/` — типы номеров
- `/api/v1/bookings/` — бронирования (создание/обновление/просмотр)
- `/api/v1/room_images/` — загрузка фото номера
- `/api/v1/auth/` — djoser (регистрация, логин, токены)

> [Вернуться в начало](#Начало)

<a name="Шаблон"></a>

### Шаблон заполнения .env-файла, расположен по пути infra/.env

> в settings.py указаны дефолтные значения для переменных из env-файла

```python
SECRET_KEY = 'Ваш секретный ключ'

DB_ENGINE=django.db.backends.postgresql # указываем, что работаем с postgresql
DB_NAME=postgres # имя базы данных
POSTGRES_USER=postgres # логин для подключения к базе данных
POSTGRES_PASSWORD=postgres # пароль для подключения к БД
DB_HOST=db # название сервиса (контейнера)
DB_PORT=5432 # порт для подключения к БД
```

> [Вернуться в начало](#Начало)

<a name="Запуск"></a>

### Запуск проекта на локальной машине

- Склонируйте репозиторий

```python
git clone git@github.com:dmsnback/bookinn.git
```

- Переходим в папку с файлом ```docker-compose.yaml```

```python
cd infra
```

- Запускаем Docker контейнеры

```python
docker-compose up -d --build
```

- Выполняем миграции

```python
docker-compose exec backend python manage.py migrate
```

- Создаём суперюзера

```python
docker-compose exec backend python manage.py createsuperuser
```

- Собираем статику

```python
docker-compose exec backend python manage.py collectstatic --no-input
```

- Наполняем базу данных содержимым из файла ```rooms_fixture.json```:

> В базу добавится 10 номеров.

```python
docker-compose exec backend python manage.py loaddata data/rooms_fixture.json
```

> __Проект станет доступен по адресу:__

[http://localhost/api/v1/](http://localhost/api/v1/)

> __Админка станет доступна по адресу:__

[http://localhost/admin/](http://localhost/admin/)

> __Документация к API будет доступна по адресу:__

[http://localhost/api/docs/](http://localhost/api/docs/)

> [Вернуться в начало](#Начало)

<a name="Авторы"></a>

### Автор

- [Титенков Дмитрий](https://github.com/dmsnback)

> [Вернуться в начало](#Начало)
Binary file added backend/.DS_Store
Binary file not shown.
10 changes: 10 additions & 0 deletions backend/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
FROM python:3.11-slim
LABEL maintainer="Dmitry Titenkov <lt200711@yandex.ru>"
LABEL version="1.0"
LABEL description="API for booking hotel rooms"
RUN mkdir /app
COPY requirements.txt /app
RUN pip3 install -r /app/requirements.txt --no-cache-dir -vvv
COPY . /app
WORKDIR /app
CMD [ "gunicorn", "bookinn.wsgi:application", "--bind", "0.0.0.0:8000" ]
File renamed without changes.
6 changes: 6 additions & 0 deletions backend/api/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from django.apps import AppConfig


class ApiConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "api"
File renamed without changes.
8 changes: 8 additions & 0 deletions backend/api/urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from django.urls import include, path
from drf_spectacular.views import SpectacularAPIView, SpectacularSwaggerView

urlpatterns = [
path("v1/", include("api.v1.urls")),
path("schema/", SpectacularAPIView.as_view(), name="schema"),
path("docs/", SpectacularSwaggerView.as_view(url_name="schema"), name="docs"),
]
File renamed without changes.
21 changes: 21 additions & 0 deletions backend/api/v1/pagination.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from rest_framework.pagination import PageNumberPagination
from rest_framework.response import Response


class CustomPagination(PageNumberPagination):
def get_paginated_response(self, data):
ordering = self.request.query_params.get("ordering", None)
return Response(
{
"links": {
"next": self.get_next_link() or None,
"previous": self.get_previous_link() or None,
},
"count": self.page.paginator.count,
"ordering": ordering,
"current_page": self.page.number,
"total_pages": self.page.paginator.num_pages,
"page_sizes": self.get_page_size(self.request),
"results": data,
}
)
21 changes: 21 additions & 0 deletions backend/api/v1/permissions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from rest_framework import permissions


class IsOwnerOrAdmin(permissions.BasePermission):
"""Разрешает доступ админу или владельцу бронирования."""

def has_object_permission(self, request, view, obj):
if request.user.is_staff or request.user.is_superuser:
return True
return obj.user == request.user


class IsAdminOrReadOnly(permissions.BasePermission):
"""Разрешаеет доступ админу с полными правами или юзеру только чтение."""

def has_permission(self, request, view):
return (
request.method in permissions.SAFE_METHODS
or request.user.is_staff
or request.user.is_superuser
)
Loading