■ FastAPI + READY
INTERVIEW SQLAlchemy
NOTES
Quick-reference patterns · Golden lines · Memory tricks · Common mistakes
■ 1 · MASTER FLOW (MOST IMPORTANT)
Every API follows this pattern
CREATE (POST)
receive → db → create object
→ add → commit → refresh → return
GET ALL
db → query → all → return
GET ONE
db → query → filter → first
→ if not found → error → return
UPDATE
db → query → filter → check
→ update → commit → return
DELETE
db → query → filter → delete → commit
■ 2 · GOLDEN LINE
Query → Filter → Action → Commit
Action Method
Get All .all()
Get One .first()
Update .update()
Delete .delete()
FastAPI + SQLAlchemy · Interview Notes · Page 1
■ 3 · QUERY vs FILTER
Query – select the table (no data yet)
[Link]([Link])
Filter – apply condition
.filter([Link] == id)
Mapping (VERY IMPORTANT)
List Logic DB Logic
for x in list query()
if x["id"] == id filter()
return x first()
■ 4 · CLASS vs VARIABLE
Rule Example Meaning
Class → Capital [Link] table / structure
Variable → small blog actual data
Common Mistake ■ [Link] WRONG – use Blog
■ 5 · SCHEMA (Pydantic)
class Blog(BaseModel):
title: str
body: str
# Usage in route:
def create(blog: [Link]):
[Link], [Link]
■ 6 · CREATE PATTERN
Write this 3 times until it's muscle memory:
FastAPI + SQLAlchemy · Interview Notes · Page 2
db = SessionLocal()
new_blog = [Link](
title=[Link],
body=[Link]
)
[Link](new_blog)
[Link]()
[Link](new_blog)
return new_blog
■ 7 · GET ONE PATTERN
db = SessionLocal()
blog = [Link]([Link])
.filter([Link] == id)
.first()
if not blog:
raise HTTPException(status_code=404,
detail="Not found")
return blog
■ 8 · UPDATE PATTERN
db = SessionLocal()
blog = [Link]([Link])
.filter([Link] == id)
if [Link]() is None:
raise HTTPException(status_code=404,
detail="Not found")
[Link]({...})
[Link]()
■ 9 · DELETE PATTERN
FastAPI + SQLAlchemy · Interview Notes · Page 3
db = SessionLocal()
blog = [Link]([Link])
.filter([Link] == id)
[Link](synchronize_session=False)
[Link]()
■ 10 · MEMORY TRICKS
Trick 1 – List → DB Mapping
List DB
loop query
if filter
return first
append add
update update
remove delete
Trick 2 – Flow Trigger
What am I doing?
→ create? → add()
→ get all? → .all()
→ get one? → filter + first()
→ update? → .update()
→ delete? → .delete()
Trick 3 – Naming
Name Meaning
Blog structure (class / table)
blog data (variable / row)
■ 11 · COMMON MISTAKES
■ [Link] ■ [Link] ← Capital B always
■ == in update dict ■ Use = inside the dict, not ==
■ missing .commit() ■ Always commit after write ops
■ missing .first() ■ Query returns Query obj, not row
FastAPI + SQLAlchemy · Interview Notes · Page 4
■ no 404 check ■ Always handle not-found case
■ FINAL ONE-LINE SUMMARY
FastAPI = route + schema + db + query/filter + action + commit
FastAPI + SQLAlchemy · Interview Notes · Page 5
■IndiaFastAPI
Placement Edition Interview
· CRUD · SQLAlchemy · Prep
Pydantic
Covers: Coding · Debugging · Conceptual · Follow-ups · Common Mistakes · Trick Questions
■ SECTION 1 · CODING QUESTIONS
Q1. Write a FastAPI route to create a Blog post using SQLAlchemy. Easy
@[Link]('/blog')
def create(blog: [Link], db: Session = Depends(get_db)):
new_blog = [Link](title=[Link], body=[Link])
[Link](new_blog)
[Link]()
[Link](new_blog)
return new_blog
■ Define POST route, accept [Link], create [Link](title=[Link], body=[Link]), [Link] → [Link]
→ [Link] → return.
■ Always refresh after commit to get DB-generated fields like id.
Q2. Write a GET route to fetch ALL blogs from the database. Easy
@[Link]('/blog')
def get_all(db: Session = Depends(get_db)):
return [Link]([Link]).all()
■ Use [Link]([Link]).all() — returns a list of all rows.
Q3. Write a GET route to fetch ONE blog by id. Handle 404. Easy
blog = [Link]([Link]).filter([Link] == id).first()
if not blog:
raise HTTPException(status_code=404, detail="Not found")
return blog
■ Query → filter by id → .first(). If None raise HTTPException(404).
■ Use .first() not .all() — filter returns a Query object, not a row.
Q4. Write an UPDATE route for a blog post. Medium
blog = [Link]([Link]).filter([Link] == id)
if not [Link]():
raise HTTPException(404, "Not found")
[Link]({'title': [Link], 'body': [Link]})
[Link]()
■ Query → filter → check .first() → call .update({}) on query → [Link]().
■ Do NOT call .first() before .update() — keep the query object.
FastAPI Interview Prep · India Placement Edition · Page 1
Q5. Write a DELETE route for a blog post. Easy
blog = [Link]([Link]).filter([Link] == id)
[Link](synchronize_session=False)
[Link]()
return {'message': 'deleted'}
■ Query → filter → .delete(synchronize_session=False) → [Link]().
■ synchronize_session=False is needed to avoid SQLAlchemy session sync issues.
Q6. Define a Pydantic schema for Blog with title and body. Easy
from pydantic import BaseModel
class Blog(BaseModel):
title: str
body: str
■ Inherit from BaseModel, declare fields with type annotations.
Q7. How do you define the Blog SQLAlchemy model (table)? Easy
class Blog(Base):
__tablename__ = 'blogs'
id = Column(Integer, primary_key=True, index=True)
title = Column(String)
body = Column(String)
■ Inherit from Base, use Column with types, define __tablename__.
Q8. How do you set up a database session dependency in FastAPI? Medium
def get_db():
db = SessionLocal()
try:
yield db
finally:
[Link]()
■ Create SessionLocal with sessionmaker, yield db in a function, use Depends().
■ yield ensures the session closes even if an error occurs.
FastAPI Interview Prep · India Placement Edition · Page 2
■ SECTION 2 · DEBUGGING QUESTIONS
Spot the bug and fix it.
Q1. What is wrong with this update code? Medium
# BUGGY CODE:
blog = [Link]([Link])
.filter([Link] == id).first()
[Link]({'title': 'new'}) # ← AttributeError!
# FIX:
blog = [Link]([Link]).filter([Link] == id)
if not [Link](): raise HTTPException(404, 'Not found')
[Link]({'title': 'new'})
[Link]()
■ BUG: .first() is called before .update(), which returns a row object — .update() is not available on it. Fix: store query,
check .first() separately, call .update() on the query.
Q2. Why does this GET route always return empty even though data exists? Easy
# BUGGY:
return [Link]([Link]).first()
# FIX:
return [Link]([Link]).all()
■ BUG: .first() used instead of .all(). .first() returns one row or None. Fix: use .all().
Q3. The blog id is never returned after creation. Why? Easy
[Link](new_blog)
[Link]()
# [Link](new_blog) ← MISSING!
return new_blog # id will be None
■ [Link](new_blog) is missing. Without it, the object won't have DB-assigned values like auto-increment id.
■ refresh() re-loads the object from DB after commit.
Q4. This route crashes with 'model has no attribute blog'. Fix it. Easy
# BUGGY:
[Link]([Link]).all()
# FIX:
[Link]([Link]).all()
■ BUG: [Link] — Python is case-sensitive. Class name is Blog (capital B). Fix: [Link].
FastAPI Interview Prep · India Placement Edition · Page 3
Q5. Why does DELETE not persist after the request ends? Easy
[Link](synchronize_session=False)
# [Link]() ← MISSING!
■ [Link]() is missing after .delete(). Without commit, the transaction is rolled back.
■ Always commit after any write operation: add, update, delete.
Q6. This Pydantic schema throws a validation error. Why? Easy
class Blog(BaseModel):
title: int # ← WRONG type
body: str
# Fix: title: str
■ BUG: title is declared as int but a string is passed. Fix: title: str.
FastAPI Interview Prep · India Placement Edition · Page 4
■ SECTION 3 · CONCEPTUAL / THEORY
Q1. What is FastAPI and why is it popular in India for placements? Easy
■ FastAPI is a modern Python web framework for building APIs. It's popular because it's fast, has automatic docs
(Swagger), uses Python type hints, and is easy to learn — ideal for backend roles.
Q2. What is the difference between Pydantic schema and SQLAlchemy model? Medium
■ Pydantic schema = data validation / input-output shape (what the API receives/returns). SQLAlchemy model =
database table structure (what is stored). They are separate layers.
■ Common interview point — they serve different purposes.
Q3. What does [Link]() do? Easy
■ It saves all pending changes in the current transaction to the database permanently. Without it, changes exist only in
memory and are lost when the session ends.
Q4. What is the difference between .all() and .first()? Easy
■ .all() returns a list of all matching rows. .first() returns the first matching row or None. .first() is used for single-item
lookups by id.
Q5. What is [Link]([Link]) doing? Does it hit the database? Medium
■ It creates a Query object targeting the Blog table. It does NOT hit the database yet — it's just building the query. The
DB is hit only when you call .all(), .first(), .count(), etc.
■ This is a common trick question!
Q6. What is the role of Depends() in FastAPI? Medium
■ Depends() is FastAPI's dependency injection. It automatically calls the function (like get_db) and passes the result to
the route. Used to inject the DB session into every route.
Q7. Why do we use yield in get_db() instead of return? Medium
■ yield makes it a generator. FastAPI runs the code before yield to open the session, passes it to the route, then runs
code after yield ([Link]()) — even if an error occurs. return would not guarantee cleanup.
■ Think of it like a try/finally block.
Q8. What HTTP status codes should you use for CRUD? Easy
■ POST=201 Created, GET=200 OK, PUT/PATCH=200 OK, DELETE=204 No Content, Not Found=404, Validation
Error=422.
Q9. What is synchronize_session=False in delete()? Hard
■ It tells SQLAlchemy not to synchronize the in-memory session objects after delete. Without it, SQLAlchemy tries to
expire/update cached objects which can cause issues in bulk deletes.
Q10. What is Base in SQLAlchemy and why do we need it? Medium
■ Base = declarative_base() — it is the base class all models inherit from. It keeps track of all models so create_all()
knows which tables to create in the DB.
FastAPI Interview Prep · India Placement Edition · Page 5
■ SECTION 4 · FOLLOW-UP QUESTIONS
Questions an interviewer asks AFTER your initial answer.
Q1. You used .all() — what if there are 1 million rows? Medium
[Link]([Link]).offset(0).limit(10).all()
■ In production, use pagination: .offset(skip).limit(limit) to fetch only a page of results at a time.
Q2. What if two requests try to update the same row at the same time? Hard
■ This is a race condition. Handle with DB-level locking or optimistic concurrency (version fields). Basic answer:
SQLAlchemy uses transactions — one will wait or fail.
■ Just mention transactions and locking — don't over-explain.
Q3. Why not just use a global db variable instead of Depends(get_db)? Medium
■ A global session is not thread-safe. Each request needs its own session to avoid data leaks between requests.
Depends() creates a fresh session per request.
Q4. How would you return only specific fields instead of the full object? Medium
class ShowBlog(BaseModel):
title: str
class Config:
orm_mode = True
@[Link]('/blog/{id}', response_model=ShowBlog)
■ Create a response Pydantic schema with only the required fields and use response_model= in the route decorator.
Q5. What happens if you forget to call [Link]() before commit? Medium
■ The object is never staged for insertion. [Link]() commits nothing — no row is inserted. No error is raised, which
makes this a silent bug.
■ Silent bugs are the hardest — always remember add → commit → refresh.
Q6. Can you filter on multiple conditions? Show how. Medium
# Multiple filters:
[Link]([Link])
.filter([Link] == id,
[Link] == 'Python')
.first()
■ Chain multiple .filter() calls or use comma-separated conditions inside a single .filter().
FastAPI Interview Prep · India Placement Edition · Page 6
■■ SECTION 5 · COMMON MISTAKES QUESTIONS
These are phrased as 'what's wrong' or 'why doesn't this work'.
Q1. A student writes [Link] instead of [Link]. What error will they get? Easy
■ AttributeError: module 'model' has no attribute 'blog'. Python is case-sensitive; class names are CamelCase by
convention.
Q2. A student uses == inside .update({}). What happens? Easy
# WRONG:
[Link]({'title' == new_title})
# RIGHT:
[Link]({'title': new_title})
■ SyntaxError or logical bug. Inside a dict, use : for key-value pairs. == is a comparison, not assignment. Correct:
.update({'title': new_title}).
Q3. After [Link](), the student tries to access new_blog.id but gets None. Why? Medium
■ [Link](new_blog) was not called. After commit, the in-memory object is not automatically updated with
DB-generated values. refresh() re-fetches from DB.
Q4. A student defines their schema class as class blog(BaseModel). What is the issue? Easy
■ Convention violation — class names should be PascalCase (Blog). While Python allows lowercase, it's a bad
practice and will confuse with variable names like blog.
Q5. A student forgets to add orm_mode = True in the response schema. What breaks? Medium
class ShowBlog(BaseModel):
title: str
class Config:
orm_mode = True # ← required for ORM objects
■ FastAPI can't serialize the SQLAlchemy ORM object to JSON. It raises a validation error. orm_mode = True tells
Pydantic to read data from ORM attributes, not just dicts.
Q6. Why does this route return 200 even when the blog doesn't exist? Easy
# BUGGY — no 404 check:
def get_blog(id: int, db: Session = Depends(get_db)):
return [Link]([Link]).filter(
[Link] == id).first()
# returns None → FastAPI returns 200 with null body!
■ The not-found check is missing. [Link]().filter().first() returns None silently — you must explicitly check and raise
HTTPException(404).
FastAPI Interview Prep · India Placement Edition · Page 7
■ QUICK CHEAT SHEET — Stick This in Your Head
Operation Pattern Key Call
CREATE add → commit → refresh → return [Link]()
GET ALL query → all .all()
GET ONE query → filter → first → check .first()
UPDATE query → filter → check → update → commit .update({})
DELETE query → filter → delete → commit .delete()
Term What It Is Mistake to Avoid
[Link] SQLAlchemy table class Never [Link]
[Link] Pydantic input validator Not the same as model
.commit() Save to DB permanently Never forget this
.refresh() Re-load object from DB Needed after create
.first() One row or None Don't use for lists
Depends() Inject session per request No global db var
orm_mode Allow ORM → Pydantic conversion Needed in response schema
■ Golden Rule
Query → Filter → Action → Commit → Return
FastAPI Interview Prep · India Placement Edition · Page 8