Skip to content

Commit 08559e4

Browse files
authored
Merge pull request #6 from dmsnback/feature/routers
crud_word, routers word, question
2 parents 88fa6da + a6b3016 commit 08559e4

6 files changed

Lines changed: 181 additions & 1 deletion

File tree

app/crud/__init__.py

Whitespace-only changes.

app/crud/words.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import logging
2+
3+
from sqlalchemy import or_, select
4+
from sqlalchemy.exc import SQLAlchemyError
5+
from sqlalchemy.ext.asyncio import AsyncSession
6+
7+
from app.models.words import Word
8+
from app.schemas.words import WordCreateSchema
9+
10+
logger = logging.getLogger(__name__)
11+
12+
13+
class CRUDWord:
14+
15+
async def create_word(self, word: WordCreateSchema, session: AsyncSession):
16+
try:
17+
new_word = Word(**word.model_dump())
18+
session.add(new_word)
19+
await session.flush()
20+
await session.commit()
21+
await session.refresh(new_word)
22+
logger.info(f"Добавлеено слово {new_word}")
23+
return new_word
24+
except SQLAlchemyError as e:
25+
logger.error(f"Ошибка при добавлении слова: {e}")
26+
raise
27+
28+
async def get_all_words(self, session: AsyncSession):
29+
try:
30+
query = select(Word)
31+
result = await session.execute(query)
32+
words = result.scalars().all()
33+
logger.info("Получен список всех слов")
34+
return words
35+
except SQLAlchemyError as e:
36+
logger.error(f"Ошибка при получении списка слов: {e}")
37+
raise
38+
39+
async def get_word(self, word: str, session: AsyncSession):
40+
try:
41+
query = select(Word).where(
42+
or_(Word.english == word, Word.russian == word)
43+
)
44+
result = await session.execute(query)
45+
find_word = result.scalars().first()
46+
if find_word:
47+
logger.info(f"Получено слово: '{find_word}'")
48+
else:
49+
logger.warning(f"Слово '{word}' не найдено в базе")
50+
return find_word
51+
except SQLAlchemyError as e:
52+
logger.error(f"Ошибка при получении слова {word}: {e}")
53+
raise

app/main.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55

66
from app.core.config import settings
77
from app.core.logging import setup_logging
8+
from app.routers.questions import question_router
9+
from app.routers.words import word_router
810

911
setup_logging()
1012

@@ -23,3 +25,6 @@ async def lifespan(app: FastAPI):
2325
description=settings.description,
2426
lifespan=lifespan,
2527
)
28+
29+
app.include_router(word_router)
30+
app.include_router(question_router)

app/routers/questions.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import random
2+
3+
from fastapi import APIRouter, Depends
4+
from sqlalchemy.ext.asyncio import AsyncSession
5+
6+
from app.core.database import get_session
7+
from app.crud.words import CRUDWord
8+
from app.schemas.words import QuestionResponseSchema
9+
10+
question_router = APIRouter(
11+
prefix="/questions",
12+
tags=[
13+
"Вопросы",
14+
],
15+
)
16+
17+
word_crud = CRUDWord()
18+
19+
20+
@question_router.get(
21+
"", response_model=QuestionResponseSchema, summary="Получение вопроса"
22+
)
23+
async def get_question(
24+
session: AsyncSession = Depends(get_session),
25+
) -> QuestionResponseSchema:
26+
words = await word_crud.get_all_words(session)
27+
if len(words) < 4:
28+
return {"error": "В базее должно быть минимум 4 слова"}
29+
30+
correct_word = random.choice(words)
31+
options_words = random.sample(words, 4)
32+
direction = random.choice(["en-ru", "ru-en"])
33+
34+
if direction == "en-ru":
35+
question_word = correct_word.english
36+
correct_answer = correct_word.russian
37+
options = [w.russian for w in options_words]
38+
else:
39+
question_word = correct_word.russian
40+
correct_answer = correct_word.english
41+
options = [w.english for w in options_words]
42+
43+
if correct_answer not in options:
44+
options[0] = correct_answer
45+
46+
random.shuffle(options)
47+
48+
return {
49+
"word": question_word,
50+
"options": options,
51+
"correct": correct_answer,
52+
"direction": direction,
53+
}

app/routers/words.py

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
from fastapi import APIRouter, Depends, HTTPException, status
2+
from sqlalchemy.ext.asyncio import AsyncSession
3+
4+
from app.core.database import get_session
5+
from app.crud.words import CRUDWord
6+
from app.schemas.words import WordCreateSchema, WordReadSchema
7+
8+
word_router = APIRouter(
9+
prefix="/words",
10+
tags=[
11+
"Слова",
12+
],
13+
)
14+
15+
word_crud = CRUDWord()
16+
17+
18+
@word_router.post(
19+
"",
20+
response_model=WordReadSchema,
21+
summary="Добавление слова",
22+
)
23+
async def add_word(
24+
word: WordCreateSchema, session: AsyncSession = Depends(get_session)
25+
) -> WordReadSchema:
26+
try:
27+
add_word = await word_crud.create_word(word, session)
28+
return add_word
29+
except Exception as e:
30+
raise e
31+
32+
33+
@word_router.get(
34+
"/all",
35+
response_model=list[WordReadSchema],
36+
summary="Получение списка всех слов",
37+
)
38+
async def get_all_words(
39+
session: AsyncSession = Depends(get_session),
40+
) -> list[WordReadSchema]:
41+
try:
42+
words = await word_crud.get_all_words(session)
43+
if not words:
44+
raise HTTPException(
45+
status_code=status.HTTP_404_NOT_FOUND,
46+
detail="Список слов отсутсттвует",
47+
)
48+
return words
49+
except Exception as e:
50+
raise e
51+
52+
53+
@word_router.get(
54+
"/{word}", response_model=WordReadSchema, summary="Получение слова"
55+
)
56+
async def get_word(
57+
word: str, session: AsyncSession = Depends(get_session)
58+
) -> WordReadSchema:
59+
try:
60+
word = word.lower()
61+
find_word = await word_crud.get_word(word, session)
62+
if not find_word:
63+
raise HTTPException(
64+
status_code=status.HTTP_404_NOT_FOUND,
65+
detail="Слово не найдено",
66+
)
67+
return find_word
68+
except Exception as e:
69+
raise e

app/schemas/words.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from pydantic import BaseModel
44

55

6-
class QuestionResponse(BaseModel):
6+
class QuestionResponseSchema(BaseModel):
77
word: str
88
options: list[str]
99
correct: str

0 commit comments

Comments
 (0)