{"id":21649473,"url":"https://github.com/alexsander-pavlov/easylibrary","last_synced_at":"2026-04-12T15:05:03.420Z","repository":{"id":263969811,"uuid":"887714813","full_name":"Alexsander-Pavlov/EasyLibrary","owner":"Alexsander-Pavlov","description":"API library","archived":false,"fork":false,"pushed_at":"2024-11-13T06:44:58.000Z","size":60,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-01-25T05:24:47.423Z","etag":null,"topics":["cachalot","cache","celery","celerybeat","cors-headers","django","django-rest-framework","docker","docker-compose","jwt-authentication","openai","permissions","poetry","postgresql","redis","rest-api"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Alexsander-Pavlov.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-11-13T06:44:40.000Z","updated_at":"2024-11-18T05:43:32.000Z","dependencies_parsed_at":"2024-11-21T09:43:15.048Z","dependency_job_id":null,"html_url":"https://github.com/Alexsander-Pavlov/EasyLibrary","commit_stats":null,"previous_names":["alexsander-pavlov/easylibrary"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Alexsander-Pavlov%2FEasyLibrary","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Alexsander-Pavlov%2FEasyLibrary/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Alexsander-Pavlov%2FEasyLibrary/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Alexsander-Pavlov%2FEasyLibrary/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Alexsander-Pavlov","download_url":"https://codeload.github.com/Alexsander-Pavlov/EasyLibrary/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244538632,"owners_count":20468755,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cachalot","cache","celery","celerybeat","cors-headers","django","django-rest-framework","docker","docker-compose","jwt-authentication","openai","permissions","poetry","postgresql","redis","rest-api"],"created_at":"2024-11-25T07:31:10.385Z","updated_at":"2026-04-12T15:05:03.362Z","avatar_url":"https://github.com/Alexsander-Pavlov.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Title\nЭтот проект является API библиотекой и решает круг типичных задач любой библиотеки.\nКакие задачи решает:\n1. Облегчает поиск нужных книг\n2. Увеличивает поток читателей\n3. Улучшает популярность библиотеки\n4. Уменьшает количество физических поситителей\n5. Разгружает библиотекаря\n6. Упрощает учет книг\n7. Упрощает отслеживание выданных книг\n\n# Utils\n## Redis, Celery\nВ проекте используется Брокер сообщений Redis и воркер Celery\n### Docker контейнер Redis\n```yaml\nredis:\n    image: redis:7.2.5-alpine\n    expose:\n      - 6379\n```\n\n### Docker контейнер Celery Worker (Сокращенная версия)\n```yaml\ncelery_worker:\n    build: \n      context: .\n      dockerfile: ./docker/django/Dockerfile\n    image: config\n    command: /start-celeryworker\n    volumes:\n      - .:/app\n    env_file:\n      - .env\n\ncelery_beat:\n    build: \n      context: .\n      dockerfile: ./docker/django/Dockerfile\n    image: config\n    command: /start-celerybeat\n    volumes:\n      - .:/app\n    env_file:\n      - .env\n```\n\n### Настройка Celery.\n```python\n# settings.py\nINSTALLED_APPS = [\n    'django_celery_beat',\n]\nCELERY_BROKER_URL = os.environ.get(\"CELERY_BROKER\")\nCELERY_RESULT_BACKEND = os.environ.get(\"CELERY_BACKEND\")\nCELERY_RESULT_EXTENDED = True\nCELERY_BROKER_CONNECTION_RETRY_ON_STARTUP = True\nCELERY_BEAT_SCHEDULER = os.environ.get('DEFAULT_DATABASE_BEAT')\nSTANDART_HOUR_TO_TASK = 8\nSTANDART_MINUTE_TO_TASK = 0\n```\n\n### Инициализация Celery\n```python\nos.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings')\napp = Celery('config')\napp.config_from_object('django.conf:settings', namespace='CELERY')\napp.autodiscover_tasks()\n```\n\n### TaskManager\n```python\n# Менеджер для работы Celery\n# Создание переодической задачи\ninstance = \u003cOrder\u003e\ntask_manager = TaskManager(instance)\ntask_manager.start_periodic_task()\n```\n```python\n# Обновление переодической задачи\ninstance = \u003cOrder\u003e\ntask_manager = TaskManager(instance)\ntask_manager.update_periodic_task()\n```\n```python\n# Удаление переодической задачи\ninstance = \u003cOrder\u003e\ntask_manager = TaskManager(instance)\ntask_manager.delete_periodic_task()\n```\n```python\n# Запуск мнгновенной задачи\ninstance = \u003cOrder\u003e\nTaskManager.launch_task(\n    instance,\n    'path/to/html.html',\n)\n```\n\n## Cachalot\nАвтоматизированный Кэш\n### Настройка\n```python\n# settings.py\nINSTALLED_APPS = [\n    'cachalot',\n]\nCACHES = {\n    'default': {\n        'BACKEND': 'django_redis.cache.RedisCache',\n        'LOCATION': os.environ.get('REDIS_CACHE'),\n    }\n}\n```\n\n### Использование\nИспользование данного функционала полностью автоматизированно.\n\n## CorsHeaders\nПроверка доступа к данном API извне посредством\nинспекции Headers.\n### Настройка\n```python\n# settings.py\nINSTALLED_APPS = [\n    'corsheaders',\n]\nCORS_ALLOWED_ORIGINS = ['http://localhost:8000']\nCSRF_TRUSTED_ORIGINS = ['http://localhost:8000']\nCORS_ALLOW_ALL_ORIGINS = False\n```\n\n### Использование\nИспользование данного функционала полностью автоматизированно.\n\n## JsonWebToken\nJWT токен позволяет производить аутентификацию и авторизацию\nна очень высоком уровке безопасности.\n### Настройка\n```python\n# settings.py\nREST_FRAMEWORK = {\n    'DEFAULT_AUTHENTICATION_CLASSES': [\n        'rest_framework_simplejwt.authentication.JWTAuthentication',\n    ]\n}\nSIMPLE_JWT = {\n    \"ACCESS_TOKEN_LIFETIME\": timedelta(hours=1)\n}\n```\n\n### Энд поинты\n```python\n# urls.py\nfrom rest_framework_simplejwt.views import (TokenObtainPairView,\n                                            TokenRefreshView)\n\n\nurlpatterns = [\n    path('api/token/',\n          TokenObtainPairView.as_view(),\n          name='token_obtain_pair',\n          ),\n     path('api/token/refresh/',\n          TokenRefreshView.as_view(),\n          name='token_refresh',\n          ),\n]\n```\n\n### Использование\nДля аутентификации необходимо перейти на \nэнд поинт по назначеному адрессу и ввести логин и пароль.\nПри правильных данных выводится JWT Bearer токен который необходимо\nиспользовать для авторизации.\n\n## OpenAI\nАвтогенерация документации на основе Энд поинтов,\nмоделей, сериализаторов.\nИспользуется библиотека YASG.\n### Настройка\n```python\n# settings.py\nINSTALLED_APPS = [\n    'drf_yasg',\n]\nSWAGGER_SETTINGS = {\n    'VALIDATOR_URL': 'http://127.0.0.1:8000'\n}\n```\n\n### Инициализация схемы\n```python\nfrom drf_yasg.views import get_schema_view\nfrom drf_yasg import openapi\n\n\nschema_view = get_schema_view(\n   openapi.Info(\n      title=\"EasyLibrary\",\n      default_version='v1',\n      description=\"This documentation is say, how to use API servise\",\n      terms_of_service=\"https://www.google.com/policies/terms/\",\n      contact=openapi.Contact(email=\"email@gmail.com\"),\n      license=openapi.License(name=\"BSD License\"),\n   ),\n   public=True,\n   permission_classes=(permissions.AllowAny,),\n)\n```\n\n### Энд поинт\n```python\nurlpatterns = [\n    path('redoc/', schema_view.with_ui('redoc', cache_timeout=0),\n         name='schema-redoc'),\n]\n```\n\n### Использование\nДля получения документации по данному проекту\nнеобходимо перейти на адресс:\nhttp://localhost/redoc/\nНа данном адрессе вы найдете всю необходимую исчерпывающую\nинформацию о каждом элементе и объекте проекта.\n\n# Validators\n## Реализованны такие классы:\n1. ValidatorSetPasswordUser\n2. YearValidator\n3. VolumeValidator\n4. PublishedValidator\n5. OrderRepeatValidator\n6. BookQuantityValidator\n7. ExtensionValidator\n8. SomeUserValidator\n9. ResponseValidator\n10. CountExtensionsValidator\n11. IsActiveOrderValidator\n\n### ValidatorSetPasswordUser\n```python\n# Проверка корректности паролей\nvalues = dict(password1='password', password2='password')\nvalidator = ValidatorSetPasswordUser('password1', 'password2')\nvalidator(values)\n```\n\n### YearValidator\n```python\n# Проверка корректности года публикации\n# Если книга опубликована, год не может быть больше чем текущий.\nvalue = dict(year_published=2020, is_published=True)\nvalidator = YearValidator('year_published', 'is_published')\nvalidator(value)\n```\n\n### VolumeValidator\n```python\n# Проверка корректности тома\n# Если указан том, необходимо так же указать номер.\n# Будет совершена проверка в рамках того что в данном томе\n# еще не присутсвует данный номер.\nvolume = \u003cVolume\u003e\nvalue = dict(volume=volume, num_of_volume=1)\nvalidator = VolumeValidator('volume', 'num_of_volume')\nvalidator(value)\n```\n\n### PublishedValidator\n```python\n# Проверка корректности данных исходя из статуса публикации.\n# Если книга не опубликована она не может иметь тираж.\n# Если книга не опубликована она не может быть лидером продаж.\nvalue = dict(\n    best_seller=True,\n    circulation=10000,\n    is_published=True,\n    )\nvalidator = PublishedValidator(\n    'best_seller',\n    'circulation',\n    'is_published',\n    )\nvalidator(value)\n```\n\n### OrderRepeatValidator\n```python\n# Проверка выдачи книги.\n# Если книга уже была выдана пользователю, то\n# данный валидатор не даст снова ее выдать.\nbook = \u003cBook\u003e\nvalue = dict(book=book)\nvalidator = OrderRepeatValidator('book')\nvalidator(value)\n```\n\n### BookQuantityValidator\n```python\n# Проверка количества книг.\n# Если книг на складе больше нет, тогда выдать ее не получится.\nbook = \u003cBook\u003e\nvalue = dict(book=book)\nvalidator = BookQuantityValidator('book')\nvalidator(value)\n```\n\n### ExtensionValidator\n```python\n# Контроль запросов на продление.\n# Данный валидатор проверяет что запросов на продление\n# еще нет, а так же если есть тогда они должны быть обработаны,\n# в ином случае пользователю стоит подождать ответа на запрос.\norder = \u003cOrder\u003e\nvalue = dict(order=order)\nvalidator = ExtensionValidator('order')\nvalidator(value)\n```\n\n### SomeUserValidator\n```python\n# Проверка пользователя.\n# Пользователь может подавать запрос на продление\n# только своего заказа книги.\norder = \u003cOrder\u003e\nvalue = dict(order=order)\nvalidator = SomeUserValidator('order')\nvalidator(value)\n```\n\n### ResponseValidator\n```python\n# Проверка состояния запроса.\n# Если по запросу был дан ответ, тогда выдать \n# повторно ответ уже не получится.\nvalue = dict(solution='wait')\nvalidator = ResponseValidator('solution')\nvalidator(value)\n```\n\n### CountExtensionsValidator\n```python\n# Проверка количество продлений.\n# Если количество продлений заказа\n# уже на границе установленного уровня, тогда подать\n# запрос больше не получится.\norder = \u003cOrder\u003e\nvalue = dict(order=order)\nvalidator = CountExtensionsValidator('order')\nvalidator(value)\n```\n\n### IsActiveOrderValidator\n```python\n# Проверка статуса книги.\n# Если книга уже была возвращена, тогда\n# заявление больше подать не получится.\norder = \u003cOrder\u003e\nvalue = dict(order=order)\nvalidator = IsActiveOrderValidator('order')\nvalidator(value)\n```\n\n# Other\n## Регистрация пользователя\nHandleCreateUser\n```python\n# Создание пользователя\n# User - модель пользователя\nuser = HandleCreateUser(User,\n                        validated_data,\n                        )\nuser.create()\n```\n\n# How to use\n## Для использования API нужно понимать, что есть 4 типа пользователей:\n1. Администратор\n2. Библиотекарь\n3. Пользователь\n4. Анонимный пользователь\n\n## Описание:\n1. Администратор может делать все и только он может создавать библиотекаря.\n2. Библиотекарь может взаимодействовать так же со всей системой, но по опеределенным правилами.\n3. Пользователь может только просматривать все таблицы, а так же брать книги если они есть в наличии и\nсоздавать заявки на продление выданной книги.\n4. Анонимный пользователь может только просматривать таблицы, не каких других действий он не может совершать.\n\n## Администратор может:\n1. Самое главное, Администратор может создавать библиотекаря и только он.\n2. Все остальное.\n\n## Библиотекарь может:\n1. Cоздавать, просматривать, редактировать, удалять Книги.\n2. Cоздавать, просматривать, редактировать, удалять Авторов.\n3. Cоздавать, просматривать, редактировать, удалять Издателей.\n4. Cоздавать, просматривать, редактировать, удалять Тома.\n5. Cоздавать, просматривать, редактировать, удалять Жанры.\n6. Открывать, просматривать, закрывать Выдачу книг.\n7. Открывать, просматривать, принимать, отказывать заявки на Продление книг.\n\n## Библиотекарь не может:\n1. Создавать, редактировать, удалять любых пользователей включая себя.\n\n## Пользователь может:\n1. Открывать, просматривать, Выдачу книг.\n2. Открывать, просматривать, заявку на Продление книг.\n3. Создавать, просматривать, редактировать, удалять свой профиль.\n\n## Пользователь не может:\n1. Все остальное.\n\n## Анонимный пользователь может:\n1. Просматривать Книги, Авторов, Издателей, Жанры, Тома.\n\n## Анонимный пользователь не может:\n1. Все остальное.\n\n# Rules\n## Правила создания и обновления Книги:\n1. Если книга опубликована - год ее написания не может быть больше ТЕКУЩЕГО.\n2. Если книга не была опубликована - год ее написания может быть больше ТЕКУЩЕГО.\n3. Если книга не была опубликована - она не может быть ЛИДЕРОМ продаж.\n4. Если книга не была опубликована - она не может иметь ТИРАЖ.\n5. Если у книги есть том - должен быть и номер присущей этой книги в ТОМЕ.\n6. Поля обязательные: author, publisher, name, age_restriction, count_pages, year_published, genre, circulation.\n\n## Правила создания и обновления Автора:\n1. Поля имя и фамилия обязательны.\n2. Поля имя и фамилия должны быть уникальной комбинацией.\n\n## Правила создания и обновления Издателя:\n1. Все поля обязательны.\n2. Имя, телефон, Эмеил, URL, должны быть уникальны (то есть не повторяться).\n\n## Правила создания и обновления Жанра:\n1. Все поля обязательны.\n\n## Правила создания и обновления Тома:\n1. Все поля обязательны.\n\n## Правила открытия выдачи книги:\n1. Нельзя выдать одну и ту же книгу тому же пользователю,\nесли книга до сих пор не была возвращена.\n2. Нельзя выдать книгу, если количество книг в библиотеке уже 0.\n\n## Правила открытия заявления на продление выдачи книги:\n1. Нельзя запросить продление, если заявление уже было подано и\nоно до сих пор в статусе \"wait\" (то есть еще не было обработано библиотекарем).\n2. Пользователь может открывать заявление только на свои книги которые были ему выданы.\n3. Можно открывать заявления только на активную выдачу книги (то есть на ту которая еще не была возвращена).\n4. Нельзя открывать заявление, если количество продлений уже 2 (можно продлевать только 2 раза).\n\n## Правила обработки заявления на продления выдачи книги:\n1. Одно заявление можно обработать только один раз, если статус заявление не 'wait' больше отвечать нельзя.\n\n\n# Install\n## Нужно заполнить файл .env всеми неоходимыми данными:\n```python\nDB_PASSWORD=password # Пароль Базы данных (использование).\nPOSTGRES_PASSWORD=password # Пароль Базы данных (настройка).\nYANDEX_HOST_USER=host # Эмеил от имени которого будет рассылка.\nYANDEX_PASSWORD_HOST=password # Пароль от Эмеила.\n```\n\n## Необходимо ввести команды:\nПроект находится под контролем системы контеризации Docker.\n```bash\ndocker-compose build\n```\n```bash\ndocker-compose up\n```\n\n# Tests\n\n## Проведение тестов\nДля проведения тестов вам нужно попасть внутрь основного контейнера\n```bash\ndocker exec -it config bash\n```\nЕсли выходит ошибка попробуйте\n```bash\ndocker exec -it config bin/bash\n```\nЗатем запустить тесты\n```bash\npython manage.py test\n```\nУ вас будет выполнено множество тестов.\n\n# API URLS\n\n## Книга\n1. http://localhost/api/book/list/ GET - просмотр списка книг.\n2. http://localhost/api/book/retrieve/\"some_book_number\"/ GET - просмотр книги.\n3. http://localhost/api/book/create/ POST - создание книги.\n4. http://localhost/api/book/update/\"some_book_number\"/ PATCH - обновление книги.\n5. http://localhost/api/book/delete/\"some_book_number\"/ DELETE - удаление книги.\n\n## Автор\n1. http://localhost/api/author/list/ GET - просмотр списка авторов.\n2. http://localhost/api/author/retrieve/\"some_author_number\"/ GET - просмотр автора.\n3. http://localhost/api/author/create/ CREATE - создание автора.\n4. http://localhost/api/author/update/\"some_author_number\"/ PATCH - обновление автора.\n5. http://localhost/api/author/delete/\"some_author_number\"/ DELETE - удаление автора.\n\n## Издатель\n1. http://localhost/api/publisher/list/ GET - просмотр списка издателей.\n2. http://localhost/api/publisher/retrieve/\"some_publisher_number\"/ GET - просмотр автора.\n3. http://localhost/api/publisher/create/ CREATE - создание издателя.\n4. http://localhost/api/publisher/update/\"some_publisher_number\"/ PATCH - обновление автора.\n5. http://localhost/api/publisher/delete/\"some_publisher_number\"/ DELETE - удаление автора.\n\n## Том\n1. http://localhost/api/volume/list/ GET - просмотр списка томов.\n2. http://localhost/api/volume/retrieve/\"some_volume_number\"/ GET - просмотр тома.\n3. http://localhost/api/volume/create/ CREATE - создание тома.\n4. http://localhost/api/volume/update/\"some_volume_number\"/ PATCH - обновление тома.\n5. http://localhost/api/volume/delete/\"some_volume_number\"/ DELETE - удаление тома.\n\n## Жанр\n1. http://localhost/api/genre/list/ GET - просмотр списка жанров.\n2. http://localhost/api/genre/retrieve/\"some_genre_number\"/ GET - просмотр жанра.\n3. http://localhost/api/genre/create/ CREATE - создание жанра.\n4. http://localhost/api/genre/update/\"some_genre_number\"/ PATCH - обновление жанра.\n5. http://localhost/api/genre/delete/\"some_genre_number\"/ DELETE - удаление жанра.\n\n## Выдача книг\n1. http://localhost/api/order/open/\"some_book_number\"/ CREATE - открытие выдачи книги.\n2. http://localhost/api/order/close/\"some_order_number\"/ DELETE - закрытие выдачи книги.\n3. http://localhost/api/order/retrieve/\"some_order_number\"/ GET - просмотр выдачи.\n4. http://localhost/api/order/list/ GET - просмотр списка выдач.\n\n## Запрос на продление выдачи\n1. http://localhost/api/extension/open/\"some_order_number\"/ CREATE - открытие заявление на продление.\n2. http://localhost/api/extension/accept/\"some_extension_number\"/ PATCH - принятие продления.\n3. http://localhost/api/extension/cancel/\"some_extension_number\"/ PATCH - отказ от продления.\n4. http://localhost/api/extension/retrieve/\"some_extension_number\"/ GET - просмотр заявления.\n5. http://localhost/api/extension/list/ GET - просмотра списка заявлений.\n\n\n# Info\nПроект состоит из ~2800 строк кода не считая тестов.\n\nТестов 101 штука.\nТестов написанно ~2500 строк кода.\n\n\n# Future Plans\n\nВ дальнейшей работе есть цель улучшить оптимизацию.\n\nУлучшения связанные с программой могут быть:\n1. Добавление таблицы \"Редакция\".\n2. Добавление таблицы \"Должники\" для санкций и штрафов.\n3. Внедрение посторонего API для оплаты штрафов например: Stripe.\n4. Логика связанная с снятием санкий по сигналу оплаты.\n5. Онлайн книги.\n6. Аудио книги.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falexsander-pavlov%2Feasylibrary","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falexsander-pavlov%2Feasylibrary","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falexsander-pavlov%2Feasylibrary/lists"}