بناء تطبيقات الويب باستخدام Django و FastAPI

يوجد في نظام بايثون البيئي العديد من الأطر المتاحة لإنشاء واجهة خلفية قوية. يعد Django و FastAPI الأكثر شيوعًا. يأتي Django مزودًا بالعديد من الميزات المبتكرة مثل ORM و البرامج الوسيطة و المصادقة ولوحة الإدارة وما إلى ذلك. ومن ناحية أخرى، يأتي FastAPI مزودًا بدعم جاهز للمزامنة وهو إطار عمل فائق السرعة وخفيف الوزن لإنشاء واجهات برمجة تطبيقات Rest.

الهدف من هذه المقالة هو استكشاف كيفية الاستفادة من قوة كلا الإطارين في الإنتاج. سنقوم أولاً بإعداد تطبيق Django البسيط ثم سننتقل نحو دمج FastAPI.

ملاحظة: تفترض هذه المقالة أنك على دراية بكل من أطر العمل و SQLAlchemy واستخدمتهما في مشاريع سابقة.

جزء جانغو

سأفترض أن لديك مشروع Django الأساسي جاهزًا، إذا لم يكن الأمر كذلك. فيما يلي البرنامج التعليمي للقيام بذلك، خطواتك الأولى مع Django: إعداد مشروع Django.

أولاً سأبدأ بإنشاء تطبيق Book

django-admin startapp book

إضافة تطبيق الكتاب إلى التطبيقات المثبتة

إضافة تطبيق الكتاب إلى التطبيقات المثبتة

إضافة نماذج المؤلف والكتاب

from django.db import models

class Author(models.Model):
    name = models.CharField(max_length=200)

class Book(models.Model):
    title = models.CharField(max_length=200)
    author = models.ForeignKey(Author,on_delete=models.CASCADE)
    published_date = models.DateField()

إجراء عمليات الترحيل وترحيل التغييرات إلى قاعدة البيانات.

python manage.py makemigrations && python manage.py migrate

قد تتمكن من رؤية كلا الجدولين الجديدين مضافين ببادئات كـ app_name في قاعدة البيانات الخاصة بك.

تأكد من إعداد هذين الجدولين. سنقوم الآن بتسجيل هذه النماذج في لوحة الإدارة وإضافة بعض كتبي المفضلة ومؤلفيها.

عينات الكتب:

المؤلفون:

أخيرًا، انتهينا من إعداد Django. و سنمضي قدمًا في إعداد FastAPI.

إعداد FastAPI

على عكس Django، يتطلب إعداد FastAPI القليل من العمل. بالنسبة للأشخاص الذين ليسوا على دراية بـ FastAPI، أوصي بمراجعة المراجع من الوثائق الرسمية قبل مواصلة المقالة.

تأكد من أن لديك الإعداد الأساسي جاهزًا لـ FastAPI وSqlalchemy مع Alembic.

وإليك كيف يبدو مشروعي:

لنبدأ بجزء قاعدة البيانات (المسمى بـ db). سنقوم بإنشاء نموذج أساسي وربط محرك قاعدة البيانات بجلسة.

هذه هي الملفات التي تتطلب عادةً البدء باتصال قاعدة البيانات.

session.py

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker

from app.core.config import settings

engine = create_engine(settings.SQLALCHEMY_DATABASE_URI, pool_pre_ping=True)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)

هذا هو الإعداد المعتاد لتهيئة إعداد الجلسة، وسنقوم ببدء تشغيل البيانات الوصفية لـ sqlalchemy. تحتوي فئة البيانات الوصفية على معلومات حول كافة الجداول الموجودة في الاتصال المحدد.

from sqlalchemy import create_engine, MetaData
from sqlalchemy.orm import sessionmaker
from app.core.config import settings

engine = create_engine(settings.SQLALCHEMY_DATABASE_URI, pool_pre_ping=True)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
metadata = MetaData(bind=engine)

والآن يأتي الجزء الذي قد تنتظره. إضافة نماذج! ألق نظرة على الملفات التي قمت بإنشائها. حاليا، كلا الملفين فارغان!

سنقوم باستيراد metadata من app.db.session والإشارة إلى الجداول الموجودة التي أنشأناها بالفعل.

books.py

from app.db.session import metadata, engine
from sqlalchemy import Table

book_table = Table('<table_name>',metadata,autoload_with=engine)

استبدل بالاسم المحدد الموجود في قاعدة البيانات. في مثالنا، سأستخدم book_book لجدول الكتاب و book_author لجدول المؤلف.

الآن الجزء الوحيد المتبقي لتعيين نموذج بالكامل هو إضافة جدول في الإعداد الخاص به.

from app.db.session import metadata, engine
from app.db.base import Base
from sqlalchemy import Table

book_table = Table('book_book',metadata,autoload_with=engine)
class Book(Base):
    __table__ = book_table

author.py

from app.db.session import metadata,engine
from app.db.base import Base
from sqlalchemy import Table

author_table = Table('book_author',metadata,autoload_with=engine)
class Author(Base):
    __table__ = author_table

نحن بحاجة إلى إخبار alembic بعدم القيام بأي ترحيل على هذه النماذج، حيث أن جانغو يدير هذه الكيانات. يمكنك أيضًا القيام بالعكس، ولكن أعتقد أن هذه نسخة أكثر تعقيدًا.

alembic/env.py

def run_migrations_offline() -> None:
    """Run migrations in 'offline' mode.

    This configures the context with just a URL
    and not an Engine, though an Engine is acceptable
    here as well.  By skipping the Engine creation
    we don't even need a DBAPI to be available.

    Calls to context.execute() here emit the given string to the
    script output.

    """
    url = config.get_main_option("sqlalchemy.url")
    context.configure(
        url=url,
        target_metadata=target_metadata,
        literal_binds=True,
        dialect_opts={"paramstyle": "named"},
    )

    with context.begin_transaction():
        context.run_migrations()

def run_migrations_online() -> None:
    """Run migrations in 'online' mode.

    In this scenario we need to create an Engine
    and associate a connection with the context.

    """
    connectable = engine_from_config(
        config.get_section(config.config_ini_section, {}),
        prefix="sqlalchemy.",
        poolclass=pool.NullPool,
    )

    with connectable.connect() as connection:
        context.configure(
            connection=connection, target_metadata=target_metadata
        )

        with context.begin_transaction():
            context.run_migrations()

هاتان طريقتان للتشغيل وإجراء عمليات الترحيل في حالة alembic. يجب عليك تغيير الكود السابق إلى الكود الموضح أدناه.

def include_object(object, name, type_, reflected, compare_to):
    if type_ == "table"  and reflected and compare_to is None:
        return False
    else:
        return True

def run_migrations_offline() -> None:
    """Run migrations in 'offline' mode.

    This configures the context with just a URL
    and not an Engine, though an Engine is acceptable
    here as well.  By skipping the Engine creation
    we don't even need a DBAPI to be available.

    Calls to context.execute() here emit the given string to the
    script output.

    """
    url = config.get_main_option("sqlalchemy.url")
    context.configure(
        url=url,
        target_metadata=target_metadata,
        literal_binds=True,
        include_object=include_object,
        dialect_opts={"paramstyle": "named"},
    )

    with context.begin_transaction():
        context.run_migrations()

def run_migrations_online() -> None:
    """Run migrations in 'online' mode.

    In this scenario we need to create an Engine
    and associate a connection with the context.

    """
    connectable = engine_from_config(
        config.get_section(config.config_ini_section, {}),
        prefix="sqlalchemy.",
        poolclass=pool.NullPool,
    )

    with connectable.connect() as connection:
        context.configure(
            connection=connection, target_metadata=target_metadata,include_object=include_object,
        )

        with context.begin_transaction():
            context.run_migrations()

تعمل الدالة include_object كما يوحي الاسم على مقارنة الجداول والتسلسلات والعلاقات التي يتم اختيارها لعمليات الترحيل.

نحن نتجنب النماذج المنعكسة، أي المأخوذة من الجداول التي تمت تهيئتها بالفعل.

هذا كل شيء، أنت الآن جاهز لتشغيل واجهات برمجة التطبيقات (APIs) الخاصة بك.

uvicorn app.main:app --reload

جرب apis على مستندات api المفتوحة. سوف تحصل على نتائج مماثلة.

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


اكتشاف المزيد من بايثون العربي

اشترك للحصول على أحدث التدوينات المرسلة إلى بريدك الإلكتروني.

اترك تعليقاً

لن يتم نشر عنوان بريدك الإلكتروني. الحقول الإلزامية مشار إليها بـ *

Scroll to Top

اكتشاف المزيد من بايثون العربي

اشترك الآن للاستمرار في القراءة والحصول على حق الوصول إلى الأرشيف الكامل.

Continue reading