SQLModel – ORM يعتمد على Pydantic لتطوير Python

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

مقدمة

SQLAlchemy وPydantic هما أداتان قويتان لمطور Python: الأولى لإدارة قواعد البيانات، والثانية للتحقق من صحة البيانات. لكن كان هناك دائمًا فجوة بينهما. الحل لهذه المشكلة هو SQLModel – ORM يعتمد على Pydantic، يجمع أفضل ما في العالمين.

يتيح لك SQLModel استخدام نماذج Pydantic المُنَمَّطة كجداول ORM في SQLAlchemy. هذا يُبسّط التطوير، ويُسرّع بناء APIs، ويزيل تكرار الكود بين نماذج قاعدة البيانات والمُسلسِلات.

ما هو SQLModel ولماذا تحتاجه

SQLModel هي مكتبة ORM حديثة للغة Python، أنشأها سيباستيان راميريز (مُنشئ FastAPI) في عام 2021. تحل واحدة من أكبر مشاكل تطوير الويب – تكرار الكود بين نماذج قاعدة البيانات ومخططات التحقق من البيانات.

المزايا الرئيسية لـ SQLModel

يوفر SQLModel للمطورين واجهة موحدة للعمل مع قواعد البيانات والتحقق من البيانات. تشمل المزايا الرئيسية:

  • نموذج بيانات موحد: نموذج واحد لقاعدة البيانات وAPI
  • تحقق تلقائي: تحقق مدمج من البيانات بفضل Pydantic
  • الأنماط (Typing): دعم كامل لأنماط Python وبيئة التطوير
  • التوافق: يعمل مع مشاريع SQLAlchemy الحالية
  • غير متزامن: دعم async/await مباشر من الصندوق

التثبيت والإعداد

التثبيت الأساسي

pip install sqlmodel

التثبيت مع التبعيات الإضافية

للعمل مع PostgreSQL:

pip install sqlmodel[postgresql]

للعمل غير المتزامن:

pip install sqlmodel[async]

التثبيت الكامل مع جميع التبعيات:

pip install "sqlmodel[postgresql,async]"

الاتصال بقاعدة البيانات

from sqlmodel import SQLModel, create_engine

# SQLite (للتطوير)
engine = create_engine("sqlite:///database.db")

# PostgreSQL
engine = create_engine("postgresql://user:password@localhost/dbname")

# MySQL
engine = create_engine("mysql+pymysql://user:password@localhost/dbname")

أساسيات العمل مع SQLModel

إنشاء نموذج أساسي

from sqlmodel import SQLModel, Field
from typing import Optional

class User(SQLModel, table=True):
    id: Optional[int] = Field(default=None, primary_key=True)
    name: str = Field(index=True)
    email: str = Field(unique=True)
    age: int = Field(ge=0, le=150)
    is_active: bool = Field(default=True)

خيارات Field

يستخدم SQLModel Field المُوسّع من Pydantic مع إمكانيات إضافية:

class Product(SQLModel, table=True):
    id: Optional[int] = Field(default=None, primary_key=True)
    name: str = Field(max_length=100, index=True)
    price: float = Field(gt=0, description="سعر المنتج")
    category_id: int = Field(foreign_key="category.id")
    created_at: datetime = Field(default_factory=datetime.now)

إنشاء الجداول في قاعدة البيانات

from sqlmodel import SQLModel, create_engine

engine = create_engine("sqlite:///database.db")

# إنشاء جميع الجداول
SQLModel.metadata.create_all(engine)

# إنشاء جدول معين
User.metadata.create_all(engine)

عمليات CRUD مع SQLModel

إنشاء السجلات

from sqlmodel import Session

# إنشاء سجل واحد
user = User(name="أحمد", email="ahmed@example.com", age=25)

with Session(engine) as session:
    session.add(user)
    session.commit()
    session.refresh(user)  # الحصول على المعرف من قاعدة البيانات
    print(f"تم إنشاء المستخدم: {user.name} برقم معرف {user.id}")

قراءة السجلات

from sqlmodel import select, Session

# قراءة جميع السجلات
with Session(engine) as session:
    users = session.exec(select(User)).all()
    for user in users:
        print(f"المستخدم: {user.name}, البريد: {user.email}")

# قراءة سجل واحد بالمعرف
with Session(engine) as session:
    user = session.get(User, 1)
    if user:
        print(f"تم العثور على: {user.name}")

# تصفية السجلات
with Session(engine) as session:
    active_users = session.exec(
        select(User).where(User.is_active == True)
    ).all()

تحديث السجلات

from sqlmodel import Session

with Session(engine) as session:
    user = session.get(User, 1)
    if user:
        user.age = 26
        session.add(user)
        session.commit()
        session.refresh(user)
        print(f"تم تحديث عمر المستخدم: {user.age}")

حذف السجلات

from sqlmodel import Session

with Session(engine) as session:
    user = session.get(User, 1)
    if user:
        session.delete(user)
        session.commit()
        print(f"تم حذف المستخدم: {user.name}")

العلاقات بين الجداول

علاقة واحد إلى متعدد

from sqlmodel import SQLModel, Field, Relationship
from typing import Optional, List

class Team(SQLModel, table=True):
    id: Optional[int] = Field(default=None, primary_key=True)
    name: str = Field(unique=True)
    members: List["User"] = Relationship(back_populates="team")

class User(SQLModel, table=True):
    id: Optional[int] = Field(default=None, primary_key=True)
    name: str
    team_id: Optional[int] = Field(default=None, foreign_key="team.id")
    team: Optional[Team] = Relationship(back_populates="members")

علاقة متعدد إلى متعدد

from sqlmodel import SQLModel, Field, Relationship
from typing import Optional, List

class UserCourse(SQLModel, table=True):
    user_id: Optional[int] = Field(default=None, foreign_key="user.id", primary_key=True)
    course_id: Optional[int] = Field(default=None, foreign_key="course.id", primary_key=True)

class User(SQLModel, table=True):
    id: Optional[int] = Field(default=None, primary_key=True)
    name: str
    courses: List["Course"] = Relationship(link_model=UserCourse)

class Course(SQLModel, table=True):
    id: Optional[int] = Field(default=None, primary_key=True)
    title: str
    users: List["User"] = Relationship(link_model=UserCourse)

التكامل مع FastAPI

يتكامل SQLModel بشكل مثالي مع FastAPI، مما يسمح باستخدام نفس النماذج لقاعدة البيانات وAPI:

from fastapi import FastAPI, HTTPException
from sqlmodel import Session, select

app = FastAPI()

@app.post("/users/")
def create_user(user: User):
    with Session(engine) as session:
        session.add(user)
        session.commit()
        session.refresh(user)
        return user

@app.get("/users/{user_id}")
def read_user(user_id: int):
    with Session(engine) as session:
        user = session.get(User, user_id)
        if not user:
            raise HTTPException(status_code=404, detail="المستخدم غير موجود")
        return user

@app.get("/users/")
def read_users():
    with Session(engine) as session:
        users = session.exec(select(User)).all()
        return users

الخلاصة

SQLModel هو أداة قوية تُبسّط تطوير تطبيقات Python من خلال دمج قواعد البيانات والتحقق من البيانات في نموذج واحد. سواء كنت تعمل مع FastAPI أو أي إطار عمل آخر، فإن SQLModel يقلل من تكرار الكود ويُسرّع عملية التطوير بشكل كبير.

ابدأ اليوم باستخدام SQLModel في مشروعك القادم، واستمتع بتجربة تطوير أكثر سلاسة وكفاءة!

توصيات