לדלג לתוכן

1.3 מסד נתונים רלציוני פתרון

פתרון תרגול – הרחבת פרויקט TRIP עם קשרים רלציוניים (מלונות וטיסות)

1. דוגמת מחלקות SQLAlchemy לקשרי many-to-many – מלונות, טיולים וטיסות

from sqlalchemy import Column, Integer, String, ForeignKey, Table
from sqlalchemy.orm import relationship, declarative_base

Base = declarative_base()

# טבלה מקשרת בין טיולים למלונות
trip_hotels = Table(
    'trip_hotels', Base.metadata,
    Column('trip_id', ForeignKey('trips.id'), primary_key=True),
    Column('hotel_id', ForeignKey('hotels.id'), primary_key=True)
)

# טבלה מקשרת בין טיולים לטיסות
trip_flights = Table(
    'trip_flights', Base.metadata,
    Column('trip_id', ForeignKey('trips.id'), primary_key=True),
    Column('flight_id', ForeignKey('flights.id'), primary_key=True)
)

class Hotel(Base):
    __tablename__ = 'hotels'
    id = Column(Integer, primary_key=True)
    name = Column(String)
    stars = Column(Integer)
    trips = relationship('Trip', secondary=trip_hotels, back_populates='hotels')

class Flight(Base):
    __tablename__ = 'flights'
    id = Column(Integer, primary_key=True)
    airline = Column(String)
    from_city = Column(String)
    to_city = Column(String)
    trips = relationship('Trip', secondary=trip_flights, back_populates='flights')

class Trip(Base):
    __tablename__ = 'trips'
    id = Column(Integer, primary_key=True)
    name = Column(String)
    people = Column(Integer)
    hotels = relationship('Hotel', secondary=trip_hotels, back_populates='trips')
    flights = relationship('Flight', secondary=trip_flights, back_populates='trips')

2. דוגמת שימוש – הוספה ושליפה

# יצירת טיול חדש עם מלונות וטיסות
h1 = Hotel(name="Hilton", stars=5)
h2 = Hotel(name="Dan", stars=4)
f1 = Flight(airline="EL AL", from_city="TLV", to_city="LHR")
f2 = Flight(airline="EasyJet", from_city="TLV", to_city="AMST")
t = Trip(name="טיול ללונדון", people=3, hotels=[h1, h2], flights=[f1, f2])
session.add_all([h1,h2,f1,f2,t])
session.commit()

# שליפת כל המלונות של טיול מסוים
trip = session.query(Trip).filter_by(name="טיול ללונדון").first()
print([hotel.name for hotel in trip.hotels])

# שליפת כל הטיולים של מלון מסוים
hotel = session.query(Hotel).filter_by(name="Hilton").first()
print([trip.name for trip in hotel.trips])

# שליפת כל הטיסות של טיול מסוים
print([flight.airline for flight in trip.flights])

# שליפת כל הטיולים של טיסה מסוימת
flight = session.query(Flight).filter_by(airline="EL AL").first()
print([trip.name for trip in flight.trips])

3. דוגמת קונטרולר בפייתון

# controllers/trip_relations_controller.py
from sqlalchemy.orm import Session

def get_hotels_for_trip(trip_id: int, db: Session):
    trip = db.query(Trip).get(trip_id)
    return [hotel.name for hotel in trip.hotels]

def get_trips_for_hotel(hotel_id: int, db: Session):
    hotel = db.query(Hotel).get(hotel_id)
    return [trip.name for trip in hotel.trips]

def get_flights_for_trip(trip_id: int, db: Session):
    trip = db.query(Trip).get(trip_id)
    return [flight.airline for flight in trip.flights]

def get_trips_for_flight(flight_id: int, db: Session):
    flight = db.query(Flight).get(flight_id)
    return [trip.name for trip in flight.trips]

4. דוגמת route-ים שמשתמשים ב-controller ב-FastAPI

# routes/trip_relations.py
from fastapi import APIRouter, Depends
from sqlalchemy.orm import Session
from database import get_db
from controllers.trip_relations_controller import (
    get_hotels_for_trip,
    get_trips_for_hotel,
    get_flights_for_trip,
    get_trips_for_flight
)

router = APIRouter()

@router.get("/trips/{trip_id}/hotels")
def hotels_for_trip(trip_id: int, db: Session = Depends(get_db)):
    return get_hotels_for_trip(trip_id, db)

@router.get("/hotels/{hotel_id}/trips")
def trips_for_hotel(hotel_id: int, db: Session = Depends(get_db)):
    return get_trips_for_hotel(hotel_id, db)

@router.get("/trips/{trip_id}/flights")
def flights_for_trip(trip_id: int, db: Session = Depends(get_db)):
    return get_flights_for_trip(trip_id, db)

@router.get("/flights/{flight_id}/trips")
def trips_for_flight(flight_id: int, db: Session = Depends(get_db)):
    return get_trips_for_flight(flight_id, db)

כל ה-endpoints יתועדו אוטומטית ב-/docs של FastAPI.

  • כך ניתן לנהל מערכת Trips שבה כל טיול יכול לכלול כמה מלונות וכמה טיסות, וכל מלון/טיסה יכולים להשתייך למספר טיולים שונים.