Skip to content

Instantly share code, notes, and snippets.

@sany2k8
Created June 18, 2025 05:26
Show Gist options
  • Save sany2k8/00ac39ee4759e792fc5edbc377fa0cc6 to your computer and use it in GitHub Desktop.
Save sany2k8/00ac39ee4759e792fc5edbc377fa0cc6 to your computer and use it in GitHub Desktop.

πŸ“˜ SQLAlchemy Relationship Types

This guide demonstrates the four common types of relationships in SQLAlchemy using realistic examples:

  • βœ… One-to-One: User β†’ UserProfile

  • βœ… One-to-Many: Blog β†’ BlogPost

  • βœ… Many-to-One: Reverse of one-to-many

  • βœ… Many-to-Many: Student ↔ Course


πŸ”— 1. One-to-One β€” User β†’ UserProfile

Each user has one profile, and each profile belongs to one user.

# Association via ForeignKey and uselist=False class User(Base): __tablename__ = "users" id = Column(Integer, primary_key=True) username = Column(String(50), unique=True, nullable=False) profile = relationship("UserProfile", back_populates="user", uselist=False)

class UserProfile(Base): tablename = "user_profiles" id = Column(Integer, primary_key=True) bio = Column(Text) user_id = Column(Integer, ForeignKey("users.id"), unique=True) user = relationship("User", back_populates="profile")

uselist=False ensures the relationship is one-to-one, not one-to-many.


πŸ“š 2. One-to-Many β€” Blog β†’ BlogPost

A blog can contain many blog posts, but each post belongs to one blog.

class Blog(Base): __tablename__ = "blogs" id = Column(Integer, primary_key=True) title = Column(String) posts = relationship("BlogPost", back_populates="blog")

class BlogPost(Base): tablename = "blog_posts" id = Column(Integer, primary_key=True) title = Column(String) content = Column(Text) blog_id = Column(Integer, ForeignKey("blogs.id")) blog = relationship("Blog", back_populates="posts")

Blog.posts is a list; BlogPost.blog is a single object.


πŸ” 3. Many-to-One β€” BlogPost β†’ Blog

This is the inverse of one-to-many. Already covered above:

# BlogPost.blog is a many-to-one reference blog_id = Column(Integer, ForeignKey("blogs.id")) blog = relationship("Blog", back_populates="posts")

πŸŽ“ 4. Many-to-Many β€” Student ↔ Course

Each student can enroll in many courses, and each course can have many students.

# Association table student_course = Table( "student_course", Base.metadata, Column("student_id", ForeignKey("students.id"), primary_key=True), Column("course_id", ForeignKey("courses.id"), primary_key=True), )

class Student(Base): tablename = "students" id = Column(Integer, primary_key=True) name = Column(String) courses = relationship("Course", secondary=student_course, back_populates="students")

class Course(Base): tablename = "courses" id = Column(Integer, primary_key=True) title = Column(String) students = relationship("Student", secondary=student_course, back_populates="courses")

secondary=student_course connects them via the join table.


πŸ§ͺ Bonus: CRUD Example (One-to-Many)

# Create a blog and posts blog = Blog(title="My Tech Blog") post1 = BlogPost(title="Intro to SQLAlchemy", content="...", blog=blog) post2 = BlogPost(title="FastAPI + SQLModel", content="...", blog=blog) session.add(blog) session.commit()

# Query posts for a blog blog = session.query(Blog).first() for post in blog.posts: print(post.title)

# Query blog for a post post = session.query(BlogPost).first() print(post.blog.title)


βœ… Summary Table

RelationshipDirectionExampleTechnique
One-to-One1 ⟷ 1User β†’ UserProfileuselist=False, unique=True FK
One-to-Many1 ⟢ *Blog β†’ BlogPostrelationship(back_populates)
Many-to-One* ⟢ 1BlogPost β†’ BlogForeignKey in child model
Many-to-Many* ⟷ *Student ↔ Coursesecondary=Table, relationship()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment