Как создать две записи с собственными сервисами в рамках одного сервиса с помощью FastAPI?

Как организовать создание объектов `user` и `property` таким образом, чтобы после создания `user` автоматически создавался `property`, ссылка на которое указывала бы на соответствующего `user`? Можете ли вы привести пример или подсказать, как это реализовать?
  • 4 января 2024 г. 10:48
Ответы на вопрос 2
Для реализации функционала, когда после создания одного объекта (`user`) автоматически создается другой объект (`property`), который связан с первым, вы можете использовать FastAPI вместе с ORM, например SQLAlchemy. Давайте рассмотрим пример создания такой логики. Предположим, у вас есть модели `User` и `Property`, а также схемы для создания этих объектов.

Ниже представлен простой пример реализации моделей и роутов для создания пользователей и свойств.

```python
from fastapi import FastAPI, HTTPException, Depends, status
from pydantic import BaseModel
from sqlalchemy import create_engine, Column, Integer, String, ForeignKey
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, relationship, Session

DATABASE_URL = "sqlite:///./test.db"

engine = create_engine(DATABASE_URL)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)

Base = declarative_base()

# Модели
class User(Base):
    __tablename__ = "users"

    id = Column(Integer, primary_key=True, index=True)
    name = Column(String, index=True)
    properties = relationship("Property", back_populates="owner")

class Property(Base):
    __tablename__ = "properties"

    id = Column(Integer, primary_key=True, index=True)
    title = Column(String, index=True)
    user_id = Column(Integer, ForeignKey('users.id'))
    owner = relationship("User", back_populates="properties")

# Создаем таблицы
Base.metadata.create_all(bind=engine)

# Схемы Pydantic
class UserCreate(BaseModel):
    name: str

class PropertyCreate(BaseModel):
    title: str

# FastAPI app
app = FastAPI()

# Dependency
def get_db():
    db = SessionLocal()
    try:
        yield db
    finally:
        db.close()

@app.post("/users/", response_model=int)
def create_user(user: UserCreate, db: Session = Depends(get_db)):
    db_user = User(name=user.name)
    db.add(db_user)
    db.commit()
    db.refresh(db_user)
    create_property_for_user(db_user.id, db)  # Создаем свойство для пользователя
    return db_user.id

def create_property_for_user(user_id: int, db: Session):
    property_data = PropertyCreate(title=f"Property for user {user_id}")
    db_property = Property(title=property_data.title, user_id=user_id)
    db.add(db_property)
    db.commit()

# Запустите сервер используя команду `uvicorn your_file_name:app --reload`
```

В этом примере:

1. Созданы модели `User` и `Property` с использованием SQLAlchemy.
2. Созданы схемы Pydantic `UserCreate` и `PropertyCreate` для валидации входящих данных.
3. Приложение FastAPI инициализируется.
4. Функция зависимости `get_db` предоставляет сессию базы данных для маршрутов.
5. Маршрут `/users/` позволяет создать нового пользователя и автоматически создает `property` для этого пользователя, вызывая функцию `create_property_for_user`.

Обратите внимание, что для упрощения примера используется SQLite, а ID пользователя возвращается в качестве ответа.

Рассмотренный сценарий является базовым примером того, как вы можете организовать автоматическое создание связанных объектов в FastAPI с использованием SQLAlchemy. Стоит обратить внимание на обработку ошибок и транзакций в реальном приложении для обеспечения надежности и целостности данных.
try
 user = ...
 db.session.add(user)
 db.session.flush((user,))
 property.user_id = user.id
 db.session.add(property)
 db.session.commit()
except
...
Похожие вопросы