Giving an example with foo and bar is not a good idea because the brain needs to decode foo to something which is known what it is.

If you start with foo and bar, and the example is complicated in the end you will have in the head only foobars and nothing will be clear.

If you give the example with real-world names. Foo is Coffee, Bar is Cookie, then it is easy.

Here is another example from SQLAlchemy where they give an example for parent-chield relations with parent and chields.

For me, it is much clear if I work with some real-world objects like User has and belongs to many Alerts which has many Users and Subscriptions. Subscriptions have and belong to many users.

Many to Many

class Alert(Base):
tablename = 'alerts'
left_id = Column(Integer, ForeignKey(''), primary_key=True)
right_id = Column(Integer, ForeignKey(''), primary_key=True)
extra_data = Column(String(50))
subscription = relationship("Subscription", back_populates="users")
user = relationship("User", back_populates="subscriptions")
class User(Base):
tablename = 'left'
id = Column(Integer, primary_key=True)
subscriptions = relationship("Alert", back_populates="user")
class Subscription(Base):
tablename = 'right'
id = Column(Integer, primary_key=True)
users = relationship("Alert", back_populates="subscription")

Many to One

class Subscription(Base):
    __tablename__ = 'subscriptions'
    id = Column(Integer, primary_key=True)
    items = relationship("Item", back_populates="subscription")

class Item(Base):
    __tablename__ = 'items'
    id = Column(Integer, primary_key=True)
    subscription_id = Column(Integer, ForeignKey(''))
    subscription = relationship("Subscription", back_populates="items")