বুঝতে পেরেছি। আপনি একদম গোড়া থেকে (লাইব্রেরি ইন্সটলসহ) একটি পরিচ্ছন্ন এবং প্রফেশনাল Student CRUD চাচ্ছেন, যেখানে সার্চ বা পেজিনেশন থাকবে না। আপনার দেওয়া ফোল্ডার স্ট্রাকচার ঠিক রেখে প্রতিটি ফাইলের কোড এবং তার নিচে প্যারামিটারসহ বিস্তারিত আলোচনা নিচে দেওয়া হলো।
দিন ২: প্রফেশনাল স্টুডেন্ট CRUD (সম্পূর্ণ গাইড)
আজ আমরা আমাদের প্রোজেক্টের জন্য একটি মজবুত ভিত্তি তৈরি করব। আমরা শিখব কীভাবে জ্যাঙ্গোর মতো আলাদা অ্যাপ তৈরি করে ডেটাবেসের সাথে কাজ করতে হয়।
🛠️ ধাপ ০: লাইব্রেরি ইন্সটল (The Tools)
প্রথমে টার্মিনালে নিচের কমান্ডটি দিয়ে প্রয়োজনীয় টুলসগুলো আপনার ভার্চুয়াল এনভায়রনমেন্টে ইন্সটল করে নিন:
Bash
pip install fastapi uvicorn sqlalchemy pydantic[email]
কেন এই লাইব্রেরিগুলো?
- FastAPI: আমাদের মূল ফ্রেমওয়ার্ক।
- Uvicorn: এটি একটি সার্ভার যা আমাদের কোড রান করে ব্রাউজারে দেখাবে।
- SQLAlchemy: এটি একটি ORM (Object Relational Mapper)। এটি পাইথন ক্লাসকে ডেটাবেস টেবিলে রূপান্তর করে। জ্যাঙ্গোতে যা
models.Model, FastAPI-তে সাধারণত আমরা SQLAlchemy ব্যবহার করি। - Pydantic: এটি ডেটা ভ্যালিডেশনের জন্য ব্যবহৃত হয়। ইউজার সঠিক ডাটা পাঠাচ্ছে কি না (যেমন: বয়স সংখ্যা কি না) তা এটি চেক করে।
📂 ধাপ ১: প্রজেক্ট স্ট্রাকচার তৈরি
আপনার দেওয়া ডেমো অনুযায়ী নিচের মতো করে ফোল্ডার এবং ফাইলগুলো তৈরি করুন:
Plaintext
fastapi_project/
├── app/
│ ├── main.py
│ ├── db/
│ │ └── session.py
│ └── apps/
│ └── students/
│ ├── models.py
│ ├── schemas.py
│ └── routes.py
└── requirements.txt
🗄️ ধাপ ২: ডাটাবেস সেশন সেটিংস (app/db/session.py)
এই ফাইলটি আমাদের অ্যাপ্লিকেশনের সাথে SQLite ডাটাবেসের সংযোগ স্থাপন করে।
Python
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
# ১. ডাটাবেস ফাইলের লোকেশন
SQLALCHEMY_DATABASE_URL = "sqlite:///./sql_app.db"
# ২. ইঞ্জিন তৈরি
engine = create_engine(
SQLALCHEMY_DATABASE_URL,
connect_args={"check_same_thread": False}
)
# ৩. সেশন ফ্যাক্টরি
SessionLocal = sessionmaker(
autocommit=False,
autoflush=False,
bind=engine
)
# ৪. বেস ক্লাস
Base = declarative_base()
# ৫. ডিপেন্ডেন্সি (Dependency)
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
📝 বিস্তারিত আলোচনা:
- create_engine: এটি ডাটাবেসের সাথে কথা বলার মূল গেটওয়ে।
connect_args={"check_same_thread": False}: এটি শুধুমাত্র SQLite-এর জন্য লাগে। এর ফলে একাধিক থ্রেড বা রিকোয়েস্ট একসাথে ডাটাবেস ব্যবহার করতে পারে।
- sessionmaker: এখান থেকেই ডাটাবেসে কাজ করার জন্য ‘সেশন’ বা অনুমতি নেওয়া হয়।
autocommit=False: আমরা নিজে থেকেdb.commit()না করা পর্যন্ত ডাটা সেভ হবে না। এটি ট্রানজাকশন নিরাপদ রাখে।autoflush=False: ডাটাবেসে অপ্রয়োজনীয় রিফ্রেশ হওয়া বন্ধ রাখে।bind=engine: এই সেশনটি কোন ইঞ্জিনের (বা ডাটাবেসের) সাথে কাজ করবে তা বলে দেয়।
- declarative_base: এটি একটি মাদার ক্লাস। আমাদের সব মডেল (টেবিল) একে ইনহেরিট করবে।
- get_db(): এটি জ্যাঙ্গোর মিডলওয়্যারের মতো। প্রতিটি রিকোয়েস্টে সেশন খুলে দেয় এবং কাজ শেষে
db.close()এর মাধ্যমে সংযোগ বিচ্ছিন্ন করে দেয়।
📐 ধাপ ৩: ডাটাবেস মডেল (app/apps/students/models.py)
এটি ডাটাবেস টেবিলের নকশা।
Python
from sqlalchemy import Column, Integer, String
from app.db.session import Base
class Student(Base):
__tablename__ = "students"
id = Column(Integer, primary_key=True, index=True)
name = Column(String, index=True)
email = Column(String, unique=True, index=True)
age = Column(Integer)
📝 বিস্তারিত আলোচনা:
- tablename: ডাটাবেসে টেবিলের নাম কী হবে তা নির্ধারণ করে।
- Column: ডাটাবেসের একেকটি ফিল্ড বা কলাম।
- primary_key=True: এটি প্রতিটি স্টুডেন্টের জন্য একটি আলাদা ও অনন্য (Unique) আইডি তৈরি করে।
- index=True: এটি ডাটাবেসকে এই কলামগুলো দ্রুত খুঁজে পেতে সাহায্য করে (সার্চিং স্পিড বাড়ায়)।
- unique=True: একই ইমেইল দিয়ে দ্বিতীয় কোনো স্টুডেন্ট ডাটাবেসে ঢুকতে পারবে না।
📝 ধাপ ৪: স্কিমা বা সিরিয়ালাইজার (app/apps/students/schemas.py)
এটি ইউজারের পাঠানো ডাটা চেক করে এবং আউটপুট ফরম্যাট ঠিক করে।
Python
from pydantic import BaseModel, EmailStr
from typing import Optional
# কমন ডাটা
class StudentBase(BaseModel):
name: str
email: EmailStr
age: int
# ইনপুট নেওয়ার জন্য (Create)
class StudentCreate(StudentBase):
pass
# আপডেট করার জন্য (সব ফিল্ড অপশনাল)
class StudentUpdate(BaseModel):
name: Optional[str] = None
email: Optional[EmailStr] = None
age: Optional[int] = None
# ডাটা দেখানোর জন্য (Response)
class StudentResponse(StudentBase):
id: int
class Config:
from_attributes = True
📝 বিস্তারিত আলোচনা:
- BaseModel: Pydantic-এর মূল ক্লাস যা ডাটা টাইপ নিশ্চিত করে।
- EmailStr: এটি চেক করে ইমেইলটি সঠিক ফরম্যাটে আছে কি না।
- Optional: জ্যাঙ্গোর
null=Trueএর মতো। আপডেটের সময় ইউজার চাইলে শুধু একটি ফিল্ড পাঠাতে পারে। - from_attributes = True: এটি SQLAlchemy-র অবজেক্টকে সরাসরি Pydantic-এর JSON ফরম্যাটে রূপান্তর করতে সাহায্য করে।
🛣️ ধাপ ৫: রাউটস বা ভিউস (app/apps/students/routes.py)
এখানেই আমাদের অ্যাপের মূল লজিক থাকে।
Python
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from typing import List
from app.db.session import get_db
from . import models, schemas
router = APIRouter(prefix="/students", tags=["Students"])
# ১. Create (তৈরি করা)
@router.post("/", response_model=schemas.StudentResponse)
def create_student(student: schemas.StudentCreate, db: Session = Depends(get_db)):
db_student = models.Student(**student.dict())
db.add(db_student)
db.commit()
db.refresh(db_student)
return db_student
# ২. Read All (সব দেখা)
@router.get("/", response_model=List[schemas.StudentResponse])
def get_all_students(db: Session = Depends(get_db)):
return db.query(models.Student).all()
# ৩. Update (পরিবর্তন করা)
@router.put("/{student_id}", response_model=schemas.StudentResponse)
def update_student(student_id: int, student_data: schemas.StudentUpdate, db: Session = Depends(get_db)):
db_student = db.query(models.Student).filter(models.Student.id == student_id).first()
if not db_student:
raise HTTPException(status_code=404, detail="Student not found")
# ইউজার শুধু যে ফিল্ডগুলো পাঠিয়েছে সেগুলো বের করা
updated_info = student_data.dict(exclude_unset=True)
for key, value in updated_info.items():
setattr(db_student, key, value)
db.commit()
db.refresh(db_student)
return db_student
# ৪. Delete (মুছে ফেলা)
@router.delete("/{student_id}")
def delete_student(student_id: int, db: Session = Depends(get_db)):
db_student = db.query(models.Student).filter(models.Student.id == student_id).first()
if not db_student:
raise HTTPException(status_code=404, detail="Student not found")
db.delete(db_student)
db.commit()
return {"message": "Successfully Deleted"}📝 বিস্তারিত আলোচনা:
- APIRouter: জ্যাঙ্গোর
urls.pyএর মতো কাজ করে। এটি স্টুডেন্ট অ্যাপের সব লিংকে মেইন অ্যাপের সাথে জুড়ে দেয়। - Depends(get_db): এটি প্রতিটি রিকোয়েস্টে সেশন ইনজেক্ট করে।
- db.add(), db.commit(): ডাটাবেসে ডাটা যুক্ত এবং পাকাপাকিভাবে সেভ করার কমান্ড।
- db.refresh(): ডাটাবেস থেকে আইডি-সহ লেটেস্ট ডাটাটি নিয়ে আসে।
🔌 ধাপ ৬: মেইন অ্যাপ (app/main.py)
Python
from fastapi import FastAPI
from app.db.session import engine, Base
from app.apps.students import routes as student_routes
# ডাটাবেস টেবিল তৈরি
Base.metadata.create_all(bind=engine)
app = FastAPI(title="Pro Student CRUD")
# রাউট রেজিস্টার করা
app.include_router(student_routes.router)
@app.get("/")
def home():
return {"message": "Welcome to Student API"}
📝 বিস্তারিত আলোচনা:
- Base.metadata.create_all: এটি জ্যাঙ্গোর
migrateকমান্ডের মতো। অ্যাপ চালু হওয়ার সাথে সাথে এটি টেবিল তৈরি করে দেয়। - include_router: স্টুডেন্ট অ্যাপের রাউটগুলোকে মেইন অ্যাপের সাথে যুক্ত করে।
🚀 সার্ভার চালু করুন:
uvicorn app.main:app --reloadএখন http://127.0.0.1:8000/docs এ গিয়ে আপনার তৈরি করা ক্লিন CRUD টেস্ট করুন।
আমি কি এখন আপনাকে শিখাব কীভাবে এই কোডগুলোকে আরও ক্লিন করার জন্য services.py ফাইলে বিজনেস লজিক সরিয়ে নিতে হয়?