از طریق منوی جستجو مطلب مورد نظر خود در وبلاگ را به سرعت پیدا کنید
استفاده از SQLAlchemy با Flask و PostgreSQL
سرفصلهای مطلب
معرفی
پایگاههای داده بخش مهمی از برنامههای کاربردی مدرن هستند زیرا دادههای مورد استفاده برای تامین انرژی را ذخیره میکنند. به طور کلی، ما از زبان پرس و جو ساختاریافته (SQL) برای انجام پرس و جوها روی پایگاه داده و دستکاری داده های داخل آن. اگرچه در ابتدا از طریق ابزارهای اختصاصی SQL انجام می شد، ما به سرعت به سمت استفاده از SQL از داخل برنامه ها برای انجام پرس و جوها رفتیم.
طبیعتا با گذشت زمان، نگاشتهای رابطه ای شی (ORM) به وجود آمد – که ما را قادر می سازد ایمن، آسان و راحت به صورت برنامه ریزی شده به پایگاه داده خود وصل شویم بدون اینکه نیازی به اجرای پرس و جوها برای دستکاری داده ها باشد.
یکی از این ORM ها است SQLAlchemy. در این پست، ما عمیق تر به ORM ها و به طور خاص SQLAlchemy می پردازیم، سپس از آن برای ایجاد یک برنامه وب مبتنی بر پایگاه داده با استفاده از فلاسک چارچوب.
ORM چیست و چرا از آن استفاده کنیم؟
نگاشت شی – رابطه ایهمانطور که از نام آن پیداست، نقشه ها اشیاء به رابطه ای موجودیت ها. در زبان های برنامه نویسی شی گرا، اشیاء تفاوت چندانی با رابطه ای موجودیت ها – آنها دارای فیلدها/ویژگی های خاصی هستند که می توانند به جای یکدیگر نگاشت شوند.
همانطور که گفته شد، از آنجایی که نگاشت یک شی به یک پایگاه داده نسبتاً آسان است، عکس آن نیز بسیار ساده است. این کار را آسان می کند process توسعه نرم افزار و کاهش احتمال اشتباهات دستی هنگام نوشتن کد SQL ساده.
مزیت دیگر استفاده از ORM ها این است که به ما کمک می کنند تا کدی را بنویسیم که به DRY پایبند باشد (خودت را تکرار نکن) اصولی که به ما اجازه می دهد هر بار که نیاز به دسترسی به پایگاه داده داریم، از مدل های خود برای دستکاری داده ها به جای نوشتن کد SQL استفاده کنیم.
ORM ها پایگاه های داده را از برنامه ما انتزاع می کنند و ما را قادر می سازند تا از چندین پایگاه داده استفاده کنیم یا به راحتی پایگاه داده را تغییر دهیم. مثلاً اگر از SQL در برنامهمان برای اتصال به پایگاه داده MySQL استفاده میکردیم، اگر بخواهیم به پایگاه داده MSSQL سوئیچ کنیم، باید کد خود را تغییر دهیم، زیرا آنها در نحو متفاوت هستند.
اگر SQL ما در چندین نقطه در برنامه ما ادغام شده باشد، ثابت می شود که این کار مشکلی است. از طریق یک ORM، تغییراتی که باید انجام دهیم فقط به تغییر چند پارامتر پیکربندی محدود می شود.
اگرچه ORM ها زندگی ما را با انتزاع کردن عملیات پایگاه داده آسان تر می کنند، باید مراقب باشیم که آنچه را که در زیر کاپوت اتفاق می افتد فراموش نکنیم زیرا این امر روش استفاده از ORM ها را نیز راهنمایی می کند. ما همچنین باید با ORM ها آشنا باشیم و آنها را بیاموزیم تا بتوانیم به طور موثرتر از آنها استفاده کنیم و این کمی منحنی یادگیری را معرفی می کند.
SQLAlchemy ORM
SQLAlchemy یک ORM است که در پایتون نوشته شده است تا به توسعه دهندگان قدرت و انعطاف پذیری SQL را بدون هیچ زحمتی استفاده از آن بدهد.
SQLAlchemy در اطراف API پایگاه داده پایتون (DBAPI پایتون) که با پایتون ارسال می شود و برای تسهیل تعامل بین ماژول های پایتون و پایگاه های داده ایجاد شده است.
DBAPI برای ایجاد ثبات و قابلیت حمل در مدیریت پایگاه داده ایجاد شده است، اگرچه ما نیازی به تعامل مستقیم با آن نداریم زیرا SQLAlchemy نقطه تماس ما خواهد بود.
همچنین ذکر این نکته ضروری است که SQLAlchemy ORM ساخته شده است روی بالای هسته SQLAlchemy – که ادغام DBAPI را مدیریت می کند و SQL را پیاده سازی می کند. به عبارت دیگر، SQLAlchemy Core ابزاری برای تولید کوئری های SQL فراهم می کند.
در حالی که SQLAlchemy ORM برنامه های کاربردی ما را به پایگاه داده آگنوستیک تبدیل می کند، مهم است که توجه داشته باشیم که پایگاه داده های خاص به درایورهای خاصی برای اتصال به آنها نیاز دارند. یک مثال خوب این است Pyscopg که یک پیاده سازی PostgreSQL از DBAPI است که وقتی در ارتباط با SQLAlchemy استفاده می شود به ما امکان می دهد با پایگاه های داده Postgres تعامل داشته باشیم.
برای پایگاه های داده MySQL، PyMySQL کتابخانه اجرای DBAPI را برای تعامل با آنها پیشنهاد می کند.
SQLAlchemy همچنین می تواند با Oracle و Microsoft SQL Server استفاده شود. برخی از نام های بزرگ در صنعت که متکی هستند روی SQLAlchemy شامل Reddit، Yelp، DropBox و Survey Monkey است.
پس از معرفی ORM، اجازه دهید یک Flask API ساده بسازیم که با پایگاه داده Postgres تعامل دارد.
فلاسک با SQLAlchemy
Flask یک میکرو فریمورک سبک وزن است که برای ساخت حداقل برنامه های کاربردی وب استفاده می شود و از طریق کتابخانه های شخص ثالث می توانیم از انعطاف پذیری آن برای ساخت برنامه های کاربردی وب قوی و غنی بهره ببریم.
در مورد ما، یک RESTful API ساده میسازیم و از آن استفاده میکنیم Flask-SQLAlchemy پسوند برای اتصال API ما به پایگاه داده Postgres.
پیش نیازها
ما استفاده خواهیم کرد PostgreSQL (همچنین به عنوان Postgres شناخته می شود) برای ذخیره داده های ما که توسط API ما مدیریت و دستکاری می شوند.
برای تعامل با پایگاه داده Postgres خود، میتوانیم از خط فرمان یا کلاینتهایی که مجهز به رابطهای کاربری گرافیکی هستند استفاده کنیم و استفاده از آنها را آسانتر و پیمایش را بسیار سریعتر کنیم.
برای سیستم عامل مک، استفاده از آن را توصیه می کنم پستیکو که بسیار ساده و شهودی است و یک رابط کاربری تمیز ارائه می دهد.
PgAdmin یک کلاینت عالی دیگر است که از تمام سیستم عامل های اصلی پشتیبانی می کند و حتی نسخه Dockerized را ارائه می دهد.
ما از این کلاینت ها برای ایجاد پایگاه داده و همچنین مشاهده داده ها در طول توسعه و اجرای برنامه خود استفاده خواهیم کرد.
با نصب های خارج از راه، اجازه دهید محیط خود را ایجاد کنیم و وابستگی هایی را که برای برنامه خود نیاز داریم نصب کنیم:
$ virtualenv --python=python3 env --no-site-packages
$ source env/bin/activate
$ pip install psycopg2-binary
$ pip install flask-sqlalchemy
$ pip install Flask-Migrate
دستورات فوق یک virtualenv را ایجاد و فعال می کند، درایور Psycopg2 را نصب می کند، flask-sqlalchemy را نصب می کند و Flask-Migrate را برای مدیریت مهاجرت های پایگاه داده نصب می کند.
Flask-Migrate
استفاده می کند المبیک، که یک ابزار انتقال پایگاه داده سبک است که به ما کمک می کند تا با ایجاد و بازآفرینی پایگاه های داده، انتقال داده ها به داخل و بین پایگاه های داده و شناسایی وضعیت پایگاه داده خود، با پایگاه داده خود به شیوه ای بسیار واضح تر تعامل داشته باشیم.
در مورد ما، لازم نیست هر بار که برنامه ما شروع می شود پایگاه داده یا جداول را دوباره ایجاد کنیم و در صورتی که هیچکدام وجود نداشته باشند، این کار را به طور خودکار برای ما انجام خواهیم داد.
پیاده سازی
ما یک API ساده برای مدیریت و دستکاری اطلاعات مربوط به خودروها خواهیم ساخت. داده ها در پایگاه داده PostgreSQL ذخیره می شوند و از طریق API عملیات CRUD را انجام خواهیم داد.
ابتدا باید آن را ایجاد کنیم cars_api
پایگاه داده با استفاده از مشتری PostgreSQL انتخابی ما:
با وجود پایگاه داده، بیایید به آن متصل شویم. ما با بوت استرپ کردن Flask API خود در قسمت شروع می کنیم apps.py
فایل:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello():
return {"hello": "world"}
if __name__ == '__main__':
app.run(debug=True)
ما با ایجاد یک برنامه Flask و یک نقطه پایانی که یک شی JSON را برمی گرداند شروع می کنیم.
برای نسخه ی نمایشی خود، از آن استفاده خواهیم کرد Flask-SQLAlchemy که یک برنامه افزودنی است که به طور خاص برای افزودن عملکرد SQLAlchemy به برنامه های Flask است.
بگذارید اکنون ادغام کنیم Flask-SQLAlchemy و فلاسک – مهاجرت به ما app.py
و ایجاد یک مدل که دادههای مربوط به خودروهای خود را که ذخیره خواهیم کرد را مشخص میکند:
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
app = Flask(__name__)
app.config('SQLALCHEMY_DATABASE_URI') = "postgresql://postgres:postgres@localhost:5432/cars_api"
db = SQLAlchemy(app)
migrate = Migrate(app, db)
class CarsModel(db.Model):
__tablename__ = 'cars'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String())
model = db.Column(db.String())
doors = db.Column(db.Integer())
def __init__(self, name, model, doors):
self.name = name
self.model = model
self.doors = doors
def __repr__(self):
return f"<Car {self.name}>"
بعد از واردات flask_sqlalchemy
، با اضافه کردن URI پایگاه داده به پیکربندی برنامه خود شروع می کنیم. این URI شامل اعتبار ما، آدرس سرور و پایگاه داده ای است که برای برنامه خود استفاده خواهیم کرد.
سپس یک نمونه Flask-SQLAlchemy به نام ایجاد می کنیم db
و برای تمام تعاملات پایگاه داده ما استفاده می شود. نمونه Flask-Migrate نامیده می شود migrate
، پس از آن ایجاد می شود و برای رسیدگی به مهاجرت های پروژه ما استفاده می شود.
این CarsModel
کلاس مدلی است که برای تعریف و دستکاری داده های ما استفاده می شود. ویژگی های کلاس نشان دهنده فیلدهایی است که می خواهیم در پایگاه داده ذخیره کنیم.
نام جدول را با استفاده از عبارت تعریف می کنیم __tablename__
در کنار ستون های حاوی داده های ما.
فلاسک با رابط خط فرمان و دستورات اختصاصی ارسال می شود. به عنوان مثال، برای شروع برنامه خود، از دستور استفاده می کنیم flask run
. برای استفاده از این اسکریپت، فقط باید یک متغیر محیطی تعریف کنیم که اسکریپت میزبان برنامه Flask ما را مشخص کند:
$ export FLASK_APP=app.py
$ flask run
* Serving Flask app "app.py" (lazy loading)
* Environment: development
* Debug mode: روی
* Running روی http://127.0.0.1:5000/ (Press CTRL+C to quit)
* Restarting with stat
* Debugger is active!
* Debugger PIN: 172-503-577
با مدل ما در جای خود، و Flask-Migrate
یکپارچه، بیایید از آن برای ایجاد استفاده کنیم cars
جدول در پایگاه داده ما:
$ flask db init
$ flask db migrate
$ flask db upgrade
ما با مقداردهی اولیه پایگاه داده و فعال کردن مهاجرت ها شروع می کنیم. مهاجرت های ایجاد شده فقط اسکریپت هایی هستند که عملیات هایی را که باید انجام شوند را تعریف می کنند روی پایگاه داده ما از آنجایی که این اولین بار است، اسکریپت فقط آن را تولید می کند cars
جدول با ستون هایی که در مدل ما مشخص شده است.
این flask db upgrade
دستور مهاجرت را اجرا می کند و جدول ما را ایجاد می کند:
در صورتی که هر ستونی را اضافه، حذف یا تغییر دهیم، همیشه میتوانیم آن را اجرا کنیم migrate
و upgrade
دستوراتی برای منعکس کردن این تغییرات در پایگاه داده ما نیز وجود دارد.
ایجاد و خواندن موجودیت ها
با وجود پایگاه داده و متصل به برنامه ما، تنها چیزی که باقی می ماند اجرای عملیات CRUD است. بیایید با ایجاد یک شروع کنیم car
، و همچنین بازیابی همه موارد موجود در حال حاضر:
@app.route('/cars', methods=('POST', 'GET'))
def handle_cars():
if request.method == 'POST':
if request.is_json:
data = request.get_json()
new_car = CarsModel(name=data('name'), model=data('model'), doors=data('doors'))
db.session.add(new_car)
db.session.commit()
return {"message": f"car {new_car.name} has been created successfully."}
else:
return {"error": "The request payload is not in JSON format"}
elif request.method == 'GET':
cars = CarsModel.query.all()
results = (
{
"name": car.name,
"model": car.model,
"doors": car.doors
} for car in cars)
return {"count": len(results), "cars": results}
ما با تعریف a شروع می کنیم /cars
مسیری که هر دو را می پذیرد GET
و POST
درخواست ها. این GET
درخواست لیستی از تمام خودروهای ذخیره شده در پایگاه داده ما را در حالی که POST
متد داده های خودرو را در قالب JSON دریافت می کند و پایگاه داده ما را با اطلاعات ارائه شده پر می کند.
برای ایجاد یک ماشین جدید، ما از CarsModel
کلاس و اطلاعات مورد نیاز برای پر کردن ستون های ما را ارائه دهید cars
جدول. پس از ایجاد یک CarsModel
شی، یک جلسه پایگاه داده ایجاد می کنیم و ما را اضافه می کنیم car
به آن
برای ذخیره ماشین خود در پایگاه داده، جلسه را از طریق commit می کنیم db.session.commit()
که تراکنش DB را می بندد و ماشین ما را نجات می دهد.
بیایید با استفاده از ابزاری مانند Postman یک ماشین اضافه کنیم:
پیام پاسخ به ما اطلاع می دهد که ماشین ما ساخته و در پایگاه داده ذخیره شده است:
می بینید که اکنون یک رکورد از خودرو در پایگاه داده ما وجود دارد.
با خودروهای ذخیره شده در پایگاه داده ما، GET
درخواست به ما کمک می کند تا همه سوابق را واکشی کنیم. ما تمام خودروهای ذخیره شده در پایگاه داده خود را با استفاده از پرس و جو می کنیم CarsModel.query.all()
تابعی که توسط Flask-SQLAlchemy ارائه شده است.
این یک لیست از CarsModel
اشیاء، که سپس آنها را قالب بندی کرده و با استفاده از درک لیست به لیست اضافه می کنیم و آن را در کنار تعداد اتومبیل های موجود در پایگاه داده خود به پاسخ ارسال می کنیم. وقتی لیست خودروها را از طریق API در Postman درخواست می کنیم:
این GET
روش روی را /cars
endpoint لیست ماشینها را همانطور که در پایگاه داده ما ظاهر میشوند و همچنین تعداد کل را برمیگرداند.
توجه داشته باشید: توجه کنید که چگونه یک وجود ندارد تنها پرس و جوی SQL موجود در کد. SQLAlchemy از آن برای ما مراقبت می کند.
به روز رسانی و حذف نهادها
تا اینجای کار، میتوانیم یک ماشین واحد بسازیم و لیستی از تمام ماشینهای ذخیرهشده در پایگاه داده دریافت کنیم. برای تکمیل مجموعه عملیات CRUD روی ماشینها در API خود، باید قابلیتهایی را برای بازگرداندن جزئیات، اصلاح و حذف یک خودرو اضافه کنیم.
متدها/افعال HTTP که برای دستیابی به این مورد استفاده خواهیم کرد، خواهند بود GET
، PUT
، و DELETE
، که در یک متد واحد به نام گرد هم می آیند handle_car()
:
@app.route('/cars/<car_id>', methods=('GET', 'PUT', 'DELETE'))
def handle_car(car_id):
car = CarsModel.query.get_or_404(car_id)
if request.method == 'GET':
response = {
"name": car.name,
"model": car.model,
"doors": car.doors
}
return {"message": "success", "car": response}
elif request.method == 'PUT':
data = request.get_json()
car.name = data('name')
car.model = data('model')
car.doors = data('doors')
db.session.add(car)
db.session.commit()
return {"message": f"car {car.name} successfully updated"}
elif request.method == 'DELETE':
db.session.delete(car)
db.session.commit()
return {"message": f"Car {car.name} successfully deleted."}
روش ما handle_car()
را دریافت می کند car_id
از URL و شی ماشین را همانطور که در پایگاه داده ما ذخیره می شود دریافت می کند. اگر روش درخواست است GET
، جزئیات خودرو به سادگی بازگردانده می شود:
برای به روز رسانی جزئیات ماشین خود، ما از PUT
روش و نه PATCH
. هر دو روش را می توان برای به روز رسانی جزئیات استفاده کرد PUT
متد یک نسخه به روز شده از منبع ما را می پذیرد و جایگزین نسخه ای می شود که در پایگاه داده ذخیره کرده ایم.
این PATCH
متد به سادگی موردی را که در پایگاه داده خود داریم بدون جایگزین کردن آن تغییر می دهد. بنابراین، برای به روز رسانی a CarsModel
ثبت در پایگاه داده ما، ما باید تمام ویژگی های ماشین خود از جمله مواردی که باید به روز شوند را ارائه دهیم.
ما از جزئیات استفاده می کنیم تا شیء ماشین خود را تغییر دهیم و این تغییرات را با استفاده از آن انجام دهیم db.session.commit()
و سپس یک پاسخ را به کاربر برگردانید:
ماشین ما با موفقیت به روز شد.
در نهایت، برای حذف یک ماشین، ما یک را ارسال می کنیم DELETE
درخواست به همان نقطه پایانی با CarsModel
شی از قبل پرس و جو شده است، تنها کاری که باید انجام دهیم این است که از جلسه فعلی استفاده کنیم تا آن را با اجرا حذف کنیم db.session.delete(car)
و تراکنش خود را برای انعکاس تغییرات ما متعهد می کنیم روی پایگاه داده:
نتیجه
برنامه های کاربردی زندگی واقعی به سادگی برنامه ما نیستند و معمولاً داده هایی را مدیریت می کنند که مرتبط هستند و در چندین جدول پخش می شوند.
SQLAlchemy به ما اجازه می دهد تا روابط را تعریف کنیم و داده های مرتبط را نیز دستکاری کنیم. اطلاعات بیشتر روی مدیریت روابط را می توان در اسناد رسمی Flask-SQLAlchemy.
برنامه ما به راحتی می تواند برای تطبیق روابط و حتی جداول بیشتر گسترش یابد. همچنین می توانیم با استفاده از Binds به چندین پایگاه داده متصل شویم. اطلاعات بیشتر روی باندها را می توان در اسناد را متصل می کند page.
در این پست به معرفی ORM ها و به طور خاص ORM SQLAlchemy پرداخته ایم. با استفاده از Flask و Flask-SQLAlchemy، یک API ساده ایجاد کردهایم که دادههای مربوط به اتومبیلها را همانطور که در یک پایگاه داده محلی PostgreSQL ذخیره شده است، نشان میدهد و مدیریت میکند.
کد منبع پروژه در این پست قابل مشاهده است روی GitHub.
(برچسبها به ترجمه)# python
منتشر شده در 1403-01-18 12:25:03