Skip to content

Commit 5395452

Browse files
authored
Merge pull request #17 from sumaro2101/develop
cache, fix DAO
2 parents af68404 + 7172eaf commit 5395452

11 files changed

Lines changed: 91 additions & 30 deletions

File tree

api_v1/tests/conftest.py

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@
99
from fastapi import FastAPI
1010
from sqlalchemy.pool import NullPool
1111

12-
from config import test_connection, settings, BaseModel
12+
from config import test_connection, settings
1313
from config import db_connection
14+
from config.models.base import Base
1415
from api_v1.routers import register_routers
1516

1617

@@ -37,9 +38,9 @@ async def app() -> AsyncGenerator[LifespanManager, Any]:
3738
@asynccontextmanager
3839
async def lifespan(app: FastAPI):
3940
async with db_setup.engine.begin() as conn:
40-
await conn.run_sync(BaseModel.metadata.create_all)
41+
await conn.run_sync(Base.metadata.create_all)
4142
yield
42-
await conn.run_sync(BaseModel.metadata.drop_all)
43+
await conn.run_sync(Base.metadata.drop_all)
4344

4445
app = FastAPI(docs_url=None,
4546
redoc_url=None,
@@ -67,3 +68,15 @@ async def client(app: FastAPI) -> AsyncGenerator[httpx.AsyncClient, Any]:
6768
async def get_async_session():
6869
async with db_setup.session() as session:
6970
yield session
71+
72+
73+
@pytest.fixture()
74+
def user_test_data():
75+
data = {
76+
"email": "user@example.com",
77+
"password": "password",
78+
"is_active": True,
79+
"is_superuser": False,
80+
"is_verified": False,
81+
}
82+
return data

api_v1/tests/test_users.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@
44

55

66
@pytest.mark.asyncio
7-
async def test_get_user_error(client: AsyncClient):
8-
response = await client.get(
9-
'/users/get',
7+
async def test_get_user_error(client: AsyncClient, user_test_data):
8+
response = await client.post(
9+
'/auth/register',
10+
json=user_test_data,
1011
)
11-
assert response.status_code == 400
12+
assert response.status_code == 201

api_v1/users/views.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from fastapi import APIRouter, Depends
22
from fastapi_users import FastAPIUsers
3+
from fastapi_cache.decorator import cache
34

45
from config.models import User
56
from api_v1.auth.backends import auth_backend
@@ -18,11 +19,11 @@
1819

1920

2021
@router.get(path='/test',
21-
response_model=UserRead,
2222
dependencies=[Depends(active_user)],
2323
)
24+
@cache()
2425
async def test_end_point(user: User = Depends(active_user)):
25-
return user
26+
return dict(name=user.email)
2627

2728

2829
router.include_router(fastapi_users.get_users_router(UserRead, UserUpdate),

async_alembic/env.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
from sqlalchemy import pool
55
from sqlalchemy.engine import Connection
6-
from sqlalchemy.ext.asyncio import async_engine_from_config, AsyncEngine
6+
from sqlalchemy.ext.asyncio import AsyncEngine
77
from sqlalchemy import engine_from_config
88

99
from alembic import context

config/alembic/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
from .alembic_helper import AlembicHelper
2+
3+
4+
__all__ = ('AlembicHelper',)

config/alembic/alembic_helper.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
from pathlib import Path
2+
from alembic.command import upgrade
3+
from alembic.config import Config
4+
from typing import ClassVar
5+
from sqlalchemy.ext.asyncio.engine import AsyncConnection
6+
7+
8+
from config import settings
9+
10+
11+
class AlembicHelper:
12+
"""
13+
Вспомогательный класс для Alembic
14+
"""
15+
config: ClassVar[Config] = Config
16+
migration_path: ClassVar[Path] = settings.alembic.MIGRATION_PATH
17+
18+
def __init__(self,
19+
sql_url: str | Path,
20+
):
21+
self.sql_url = sql_url
22+
23+
def get_config(self, connection: AsyncConnection) -> Config:
24+
cfg = self.config()
25+
cfg.set_main_option('sqlalchemy.url',
26+
self.sql_url)
27+
cfg.set_main_option('script_location',
28+
self.migration_path.as_posix())
29+
cfg.attributes['connection'] = connection
30+
return cfg
31+
32+
def make_upgrade(self, connection: AsyncConnection):
33+
config = self.get_config(connection=connection)
34+
upgrade(config, 'head')

config/config.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ class AlembicSettings(BaseModel):
2727
Настройки Alembic
2828
"""
2929
CONFIG_PATH: Path = Path('alembic.ini')
30-
MIGRATION_PATH: Path = Path('async_alembic/')
30+
MIGRATION_PATH: Path = Path('async_alembic')
3131

3232

3333
class TestDBSettings(BaseModel):

config/dao/base_dao.py

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -140,20 +140,14 @@ def struct_options_statment(model: BaseModel,
140140
Returns:
141141
Select: Экземпляр запроса
142142
"""
143-
if one_to_many and many_to_many:
144-
stmt = (Select(model)
145-
.filter_by(**kwargs)
146-
.options(joinedload(*one_to_many))
147-
.options(selectinload(*many_to_many)))
148-
elif one_to_many:
149-
stmt = (Select(model)
150-
.filter_by(**kwargs)
151-
.options(joinedload(*one_to_many)))
152-
elif many_to_many:
153-
stmt = (Select(model)
154-
.filter_by(**kwargs)
155-
.options(selectinload(*many_to_many)))
156-
else:
157-
stmt = (Select(model)
158-
.filter_by(**kwargs))
143+
stms_one_to_many = ([selectinload(join) for join in one_to_many]
144+
if one_to_many
145+
else list())
146+
stmt_any_to_many = ([joinedload(join)for join in many_to_many]
147+
if many_to_many
148+
else list())
149+
stmt = (Select(model)
150+
.filter_by(**kwargs)
151+
.options(*stms_one_to_many)
152+
.options(*stmt_any_to_many))
159153
return stmt

config/database/db_helper.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ class DataBaseHelper:
2929
:function:`DataBaseHelper.session_geter` - Получение генератора текущей сессии.
3030
:function:`DataBaseHelper.get_scoped_session` - Получение текущей сессии.
3131
:function:`DataBaseHelper.dispose` - Закрытые соединения.
32-
32+
3333
## Примеры:
3434
```python
3535
from fastapi import FastAPI

main.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
11
from contextlib import asynccontextmanager
22
from fastapi import FastAPI
3+
from fastapi_cache import FastAPICache
4+
from fastapi_cache.backends.redis import RedisBackend
5+
from fastapi_cache.decorator import cache
6+
7+
from redis import asyncio as aioredis
38

49
from api_v1 import register_routers
510
from app_includes import (
611
register_errors,
712
register_middlewares,
813
register_prometheus,
914
)
15+
from config import settings
1016

1117

1218
def start_app() -> FastAPI:
@@ -23,7 +29,15 @@ def start_app() -> FastAPI:
2329

2430
@asynccontextmanager
2531
async def lifespan(app: FastAPI):
32+
redis = aioredis.from_url(settings.redis.redis_url)
33+
FastAPICache.init(RedisBackend(redis), prefix='fastapi-cache')
2634
yield
2735

2836

2937
app = start_app()
38+
39+
40+
@app.get(path='/test')
41+
@cache()
42+
async def test_end_point():
43+
return dict(hello='world')

0 commit comments

Comments
 (0)