Пользователь не добавляется в БД через эндпоинт в FastAPI приложении
Не добавляется в БД пользователь через эндпоинт в FastAPI приложении. Прошу ваших советов, предположений по решению задачи.
На данный момент сделал
- проверил pgadmin. БД успешно создана.
- после
alembic init alembic
в конфиге alembic.ini установил sqlalchemy.url:
sqlalchemy.url = postgresql://%(DB_USER)s:%(DB_PASS)s@%(DB_HOST)s:%(DB_PORT)s/%(DB_NAME)s
- успешно прошли
alembic revision --autogenerate -m 'Create tables'
иalembic upgrade head
.
Модули
- в alembic/env.py добавлено:
from auth.database import Base
from core.config import settings
target_metadata = Base.metadata
section = config.config_ini_section
config.set_section_option(section, "DB_HOST", settings.DB_HOST)
config.set_section_option(section, "DB_PORT", settings.DB_PORT)
config.set_section_option(section, "DB_NAME", settings.DB_NAME)
config.set_section_option(section, "DB_USER", settings.DB_USER)
config.set_section_option(section, "DB_PASS", settings.DB_PASS)
app/core/config.py:
import os
from pathlib import Path
from dotenv import load_dotenv
from pydantic import BaseModel
from pydantic_settings import BaseSettings
BASE_DIR = Path(__file__).parent.parent
env_path = Path(".") / ".env"
load_dotenv(dotenv_path=env_path)
class Settings(BaseSettings):
DB_USER: str = os.getenv("DB_USER")
DB_PASS: str = os.getenv("DB_PASS")
DB_HOST: str = os.getenv("DB_HOST")
DB_PORT: str = os.getenv("DB_PORT")
DB_NAME: str = os.getenv("DB_NAME")
DATABASE_URL: str = (
f"postgresql+asyncpg://{DB_USER}:{DB_PASS}@{DB_HOST}:{DB_PORT}/{DB_NAME}"
)
settings = Settings()
database.py:
from sqlalchemy import Column
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, Session
from core.config import settings
DATABASE_URL = settings.DATABASE_URL
# metadata = sqlalchemy.MetaData()
# Base = declarative_base(metadata=metadata)
Base = declarative_base()
async_engine = create_async_engine(DATABASE_URL, echo=True)
async_sessionmaker = sessionmaker(
async_engine, class_=Session, expire_on_commit=False, autoflush=False
)
# async_sessionmaker = sessionmaker(async_engine, expire_on_commit=False, autoflush=False)
async def init_db():
async with async_engine.begin() as conn:
# await conn.run_sync(SQLModel.metadata.drop_all)
await conn.run_sync(Base.metadata.create_all)
async def get_session() -> AsyncSession:
async_session = sessionmaker(
async_engine, class_=AsyncSession, expire_on_commit=False
)
async with async_session() as session:
yield session
class UserModel(Base):
__tablename__ = "users"
username = Column(sqlalchemy.String, primary_key=True, index=True)
password = Column(sqlalchemy.String)
async def create_database():
async with async_engine.begin() as conn:
await conn.run_sync(Base.metadata.create_all)
async def get_user(username: str) -> UserModel:
async with async_sessionmaker() as session:
return await session.execute(
sqlalchemy.select(UserModel).filter(UserModel.username == username)
)
async def create_user(username: str, password: str):
async with async_sessionmaker() as session:
async with session.begin():
user = UserModel(username=username, password=password)
session.add(user)
await session.commit()
auth.py:
from fastapi import APIRouter, Form, HTTPException, Depends
from starlette import status
from auth.database import get_user, create_user
from auth.utils import hash_pwd, check_pwd, encode
from schemas.pydantic_schemas import UserSchema, Token
router = APIRouter(prefix="/auth")
@router.post("/add_user_to_db")
async def add_user_to_db(user: str, password: str):
try:
await create_user(username=user, password=password)
except Exception as e:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=f"User was not added to the database. Error {str(e)} ",
)
Содержимое файла миграции на всякий случай:
"""Create tables
Revision ID: 13a3ba96a022
Revises:
Create Date: 2024-03-16 12:45:33.653702
"""
from typing import Sequence, Union
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision: str = '13a3ba96a022'
down_revision: Union[str, None] = None
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None
def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('users',
sa.Column('username', sa.String(), nullable=False),
sa.Column('password', sa.String(), nullable=True),
sa.PrimaryKeyConstraint('username')
)
op.create_index(op.f('ix_users_username'), 'users', ['username'], unique=False)
# ### end Alembic commands ###
def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.drop_index(op.f('ix_users_username'), table_name='users')
op.drop_table('users')
# ### end Alembic commands ###
Результат отправки запроса
'http://127.0.0.1:8000/auth/add_user_to_db?user=sam&password=zxc' \
-H 'accept: application/json' \
-d ''
{
"detail": "User was not added to the database. Error __aenter__ "
}
Гпт говорит: Сообщение об ошибке указывает на то, что возникла проблема с менеджером контекста aenter. Обычно это происходит, когда вы пытаетесь использовать объект в асинхронном контексте, но что-то идет не так при его использовании. Проблема, предположительно, связана с вызовом create_user.
Ответы (1 шт):
Возможно проблема в том, что ты не сделал comit
, после того как внес изменения в бд, поэтому транзакция не прошла и ничего не сохранилось.