Как связать две модели в SQLAlchemy так, чтобы в результате запроса можно было получить не только id свойство, но и его описание?

Как можно получить значение `status_description` из модели `GateStatus`, а не просто идентификатор `status_id`, при извлечении данных модели `Gate`, используя FastAPI?
  • 5 августа 2024 г. 13:23
Ответы на вопрос 1
Для работы с двумя связанными моделями в SQLAlchemy и получения значения описания свойства вместо его идентификатора, можно использовать отношения и объединения (joins) при выполнении запросов.

Пример кода:

```python
from sqlalchemy import create_engine, Column, Integer, String, ForeignKey
from sqlalchemy.orm import relationship, sessionmaker
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()

class Gate(Base):
    __tablename__ = 'gate'
    
    id = Column(Integer, primary_key=True)
    status_id = Column(Integer, ForeignKey('gate_status.id'))
    
    status = relationship("GateStatus")

class GateStatus(Base):
    __tablename__ = 'gate_status'
    
    id = Column(Integer, primary_key=True)
    status_description = Column(String)

# Создание соединения с базой данных
engine = create_engine('sqlite:///test.db')
Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine)
session = Session()

# Пример запроса, который получает все записи из модели Gate и их соответствующие описания статусов из модели GateStatus
gates = session.query(Gate).join(GateStatus).all()

for gate in gates:
    print(f"Gate id: {gate.id}, Status Description: {gate.status.status_description}")
```

Чтобы получить значение `status_description` из модели `GateStatus` при извлечении данных модели `Gate` с использованием FastAPI, можно изменить модель `Gate` и добавить метод, который будет возвращать описание статуса:

```python
from sqlalchemy.ext.automap import automap_base

Base = automap_base()

class Gate(Base):
    __tablename__ = 'gate'
    
    id = Column(Integer, primary_key=True)
    status_id = Column(Integer, ForeignKey('gate_status.id'))
    
    status = relationship("GateStatus")
    
    def get_status_description(self):
        return self.status.status_description
```

Затем в FastAPI контроллере можно использовать этот метод для получения описания статуса:

```python
from fastapi import FastAPI
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from models import Gate

app = FastAPI()

engine = create_engine('sqlite:///test.db')
Session = sessionmaker(bind=engine)

@app.get("/gates/{gate_id}")
def get_gate(gate_id: int):
    session = Session()
    gate = session.query(Gate).filter(Gate.id == gate_id).first()
    if gate:
        return {'id': gate.id, 'status_description': gate.get_status_description()}
    return {'message': 'Gate not found'}
```

Теперь при выполнении запроса по адресу `/gates/{gate_id}` вы будете получать не только ID ворот, но и их описания статусов.
Похожие вопросы