کار با Flask-SQLAlchemy در Flask

توی این پست میخوام یه مرور سریع بر برخی ویژگی ها و امکانات Flask-SQLAlchemy برای وب اپلیکیشن های Flask بزارم کتابخونه SQLALchemy یه ORM (Object–relational mapping) برای زبان پایتون هست که برای ارتباط راحت تر با پایگاه داده یا دیتابیستون هست برای درک بهتر کار ORM بزارید یه مثال بزنم تا کامل بفهمید: قبل از ORM ها برنامه نویس ها میومدن و کد های SQL هم بین کد های بک اندشون می نوشتن (هر چند که الان هم بعضی از php دولوپر هایی که بدون framework وب میزنن هم این کار می کنن ) , و عملا هم کد خواناییش کمتر می شد و هم زیاد میشد وگاهی میتونست مشکل ساز هم بشه (SQL Injection) اما حالا کار اصلی ORM ها چیه؟ به زبون خیلی ساده ORM ها میان کد های زبان برنامه نویسی رو به QUERY تبدیل می کنن و تمام مشکلات شما در ارتباط گرفتن Query زدن برداشتن اطلاعات از دیتابیش آپدیت کردن و ... رو براتون هندل می کنن یعنی شما به زبان Python کد میزنید اما در پس زمینه این کد به مثلا SQL تبدیل میشه یه مزیت دیگه که نسبتا خیلی خوبه اینه نیاز نیست برای Query زدن دیگه نگران سینتکس یا چیز دیگه باشد و عملا شما می یایید و میتونید خیلی راحت engin ORM رو عوض کنید و مثلا از MYSQL برید روی POSTGRES و یا SQLite یا خیلی از دیتابیس های دیگه و کدتون کار میکنه بدون هیچ اروری !https://fa.wikipedia.org/wiki/%D8%A7%D9%88_%D8%A2%D8%B1_%D8%A7%D9%85خب حالا فهمیدیم ORM چیه ؟ پس میدونیم SQLALchemy یه ORM هست برای زبان پایتون حالاFlask-Sqlalchemy یه اکستنشن برای برنامه های Flask هست که میاد از همون SQLALchemy استفاده می کنه و میاد اونو قابل استفاده و راحت تر میکنه برای برنامه های فلسک داکیومنت Flask-Sqlalchemy : https://flask-sqlalchemy.palletsprojects.com/داکیومنت Sqlalchemy :https://sqlalchemy.org/برای استفاده اول باید پکیج Flask-Sqlachemy رو بر روی سیستم نصب کنیمpip install flask-sqlalchemy https://pypi.org/project/flask-sqlalchemy/بعد میتونیم توی اپ فلسک امون ازش استفاده کنیم from flask import Flask app = Flask(__name__) @app.route(/) def index(): return `Hello, world`خب برای استفاده باید از flask-sqlalchemy کلاس SQLAlchemy رو import کنیمfrom flask_sqlalchemy import SQLAlchemy و حالا باید یه instance ازش بسازیم اما قبلش باید چند تا تنظیمات ست کنیم براش (مثل نوع دیتابیس, نام کاربری ,و ... )باید توی کانفیگ های app اصلی فلسکمون چند مورد رو تنظیم کنیم SQLALCHEMY_DATABASE_URI باید این مورد رو برای اتصال به دیتابیستون آدرس دهی کنیم, ما برای سادگی از sqlite استفاده می کنیم اما برای باقی هم مشابه هست برای مثال برای MariaDb یا MySql میتونید از درایور pymysql برای اتصال استفاده کنیدapp.config[SQLALCHEMY_DATABASE_URI] =`sqlite:///app.db`# SQLite, relative to Flask instance path sqlite:///project.db # PostgreSQL postgresql://scott:tiger@localhost/project # MySQL / MariaDB mysql://scott:tiger@localhost/project https://flask-sqlalchemy.palletsprojects.com/en/3.0.x/config/خب حالا ما instance خودمون رو میتونیم بسازیم db = SQLAlchemy(app)و حالا میتونیم با دیتابیسمون کار کنیمتا الان نمای کلی کد اینجوریهfrom flask import Flask from flask_sqlalchemy import SQLAlchemy # new app = Flask(__name__) # configure connection to database app.config[SQLALCHEMY_DATABASE_URI] = `sqlite:///app.db` # new db = SQLAlchemy(app) # new @app.route(&quot/&quot) def index(): return `Hello World` خب حالا ستاپ کلی تموم شد !حالا باید با این کتابخونه کار کنیم خب اولین چیزی که میاد توی ذهن هر کسی اینه ؟چجوری باید Query بزنیم به دیتابیس؟!خب اول بیایید بینیم چجوری باید جداول دیتابیس رو ساختبه طور کلی اگر با ORM های دیگه مثل Django orm کار کرده باشید میدونید برای ساخت جداول باید یه کلاس بسازیم که از مدل اصلی (مدل پایه) ارث بری می کنه بیایید یه کلاس مدل خیلی ساده برای یه کاربر همراه با فیلد های `نام کاربری `و `پسورد `و `تاریخ ` درست کنیم گام اول باید یه کلاس ایجاد کنیم class Users(db.Model): # db.Model : base class id = db.Column(db.Integer, primary_key=True) username = db.Column(db.Text(), unique=True, nullable=False) password = db.Column(db.Text() unique=True, nullable=False)بر خلاف زمانی که بدون ORM میومدیم و کد های SQL رو مینوشتیم برای ایجاد دیتابیس و جدول هاش اما توی ORM ما میاییم کد های همون زبان رو مینویسیم و ORM خودش در نهایت میاد اون کد های رو به SQL و یا ... تبدیل می کنه خب زیاد راجب کلاس ها و فیلد ها نمیخوام توضیح بدم چون تا فردا طول میکشه ولی میتونید برای کسب اطلاعات بیشتر به https://flask-sqlalchemy.palletsprojects.com/en/2.x/models/ برید و کامل مطالعه کنیدخب حالا که مدلمون رو ساختیم احتیاج داریم یه جورایی به ORM بگیم جدوال رو بساز برای داخل دیتابیس برای هم میتونیم از db.create_all() # برای ساختن تمام جداول db.drop_all() # برای حذف تمامی جداولاستفاده کنیم برای ساخت جداول, فلسک هم مثل جنگو یه shell درونی داره برای استفاده ازش کافیه توی ترمینال بزنیم flask shell میاد توی همون دایرکتوری که هستیم دنبال اپ فلسک میگرده وقتی پیداش کرد لودش میکنه و میتونید استفاده کنید برای ساخت جدوال میخوام از روش shell استفاده کنم پس توی مسیر فایل اصلی دستور زیر رو میزنم$ flask shell Python 3.10.6 (main, Nov 14 2022, 16:10:14) [GCC 11.3.0] on linux App: app Instance: /mnt/c/Users/alisharify/Documents/instance >>> و حالا توی این shell به تموم اجزای برنامه امون دسترسی داریم برای شروع فقط میاییم db رو import میکنیم تا بتونیم جداولمون رو بسازیم >>> from app import db >>> db.create_all() >>> چون ما از Sqlite استفاده می کنیم و file base هست باید فایل دیتابس در کنار مسیر اصلی پروژه امون ایجاد بشه $ ls app.db app.py $خب حالا میتونیم با دیتابسمون کار کنیم خب حالا که تا اینجاد کار های زیرکردیم نصب sqlalchemy پیکربندی sqlalchemy ایجاد دیتابیسو حالا تنها مونده که چجوری عملیات CRUD (CREATE - READ - UPDATE - DELETE)رو انجام بدیم برای شروع بیایید ببینیم چجوری باید یه نمونه جدید ایجاد کنیم توی دیتابیسمون خب دوباره flash shell رو باز می کنیم و کلاس User و Db رو ایمپورت میکنیم $ flask shell Python 3.10.6 (main, Nov 14 2022, 16:10:14) [GCC 11.3.0] on linux App: app Instance: /mnt/c/Users/netadmin/Documents/instance >>> >>> from app import User, db >>>خب برای ایجاد نمونه برای هر کدوم از جدول هامون باید از کلاس سازنده اش کمک بگیریم و برای ایجاد هر رکورد باید یه instance از اون بسازیم که توی این مورد کلاس ما User هست که بالا ساختیم>>> news_user = User(username=`alisharify`, password=`super secure pass!`) اما هنوز به طور کامل رکورد ما ایجاد نشده و توی دیتابیس قرار نگرفته برای این کار باید اول این آبجکت تازه که ساختیم رو Add کنیم به session و بعد هم commit کنیم یه جورایی یه عملیات دو مرحله ای هست هر کاری که انجام میدید, اول میایید به session اضافه اش می کنید و در انتها commit می کنید>>> db.session.add(news_user) >>> db.session.commit() >>>خب الان رکورد ما وارد دیتابیس شد و برای صحت موضوع میتونیم با Sqlite چکش کنیم$ sqlite3 app.db SQLite version 3.37.2 2022-01-06 13:25:41 Enter .help for usage hints. sqlite> .schema CREATE TABLE users ( id INTEGER NOT NULL, username TEXT NOT NULL, password TEXT NOT NULL, PRIMARY KEY (id), UNIQUE (username), UNIQUE (password) ); sqlite> خب حالا که جدول هامون تی دیتابیس ایجاد شد میتونیم شروع query زدن به دیتابیس کنیم برای query زدن به هر جدول باید با استفاده از کلاس سازنده اش و متد query این کارو کنیم >>> Users.query.all() >>> [ ]با متد all میتونیم کل دیتابیس رو دریافت کنیم یه چیزی تو مایه های * توی sql هست برای query زدن بر اساس id (primary key) باید با متد get اینکار رو کنیم>>> Users.query.get(1) >>>و برای دریافت بر اساس شرط خاصی از filter استفاده می کنیم(میتونیم از filter_by هم استفاده کنیم)# using filter() >>> Users.query.filter(Users.id == 1).first() or .all() # using filter_by >>> Users.query.filter_by(id=1).first() or .all() خب تا اینجا بسته بریم حالا یه دیتایی وارد دیتابیس کنیم و دوباره query بزنیم برای وارد کردن اطلاعات به دیتابیس باید یه آبجکت از کلاسش بسازیم >>> new_User = Users(username=alisharify, password=password)یک مورد به این صورت میتونیم آبجکت بسازیم >>> new_User = Users() >>> new_User.username = `alisharify` >>> new_User.password =` password` >>> پس از ساختن هنوز این دیتاها وارد دیتابس ما نشدن برای صحتش (خب دیگه بلدیم به دیتابیس query بزنیم) میتونیم چک کنیم>>> users = Users.query.filter(Users.username == `alisharify`).first() >>> users None و اینطور که می بینیم هنوز دیتا توی دیتابیس نیست باید یه چند مرحله دیگه هم پیش بریم تا وارد دیتابیس بشههر سری که ابجکتی از کلاس های سازنده اتون میسازید باید اول اددش کنید به session و بعد کامیتش کنید یه جورایی اگر با گیت کار کرده باشید مثل فکر کنید بهش :)برای این کار باید به صورت زیر عمل کنیم >>> db.session.add(new_User) >>> db.session.commit() >>> حالا دیتای ما وارد دیتابیس شد>>> user = Users.query.filter(Users.username == `alisharify`).first() >>> user <Users 1> >>> user.username ` alisharify `تا اینجای کار ما تونستیم READ و CREATE رو انجام بدیم حالا باید بتونیم UPDATE و DELETE رو هم انجام بدیم برای آپدیت کردن اول باید اون آبجکت رو query بزنیم و دریافت کنیم بعد تغییرش بدیم و دوباره به session اددش کنیم و کامیتش کنیمخب بیایید این کارو انجام بدیم# get user object from db >>> user_db = Users.query.filter(Users.username == `alisharify`).first() # change username >>> user_db.username = `new ali sharify` # add to session new changes >>> db.session.add(user_db) # commit new changes to database >>> db.session.commit() >>> و وقتی تغییر دادیم میتونیم دوباره query بزنیم و اطلاعات تغییر یافته رو ببینیم>>> user_db = Users.query.filter(Users.username ==` new ali sharify`).first() >>> user_db <Users 1> >>> user_db.username `new ali sharify` >>>و میتونم ببینیم که تغییر کرده حالا تنها یه مورد مونده اونم حذف کردن رکوردی از دیتابیسه برای این کار دوباره اول باید اون رکورد رو query بزنیم و دریافت کنیم >>> user_db = Users.query.filter(Users.username == `new ali sharify`).first()و بعد با متد delete ابجکت خروجی رو پاس میدیم به این متد و بعدش باید commit کنیم >>> db.session.delete(user_db) >>> db.session.commit() >>> و آبجکت ما پاک شد از دیتابیسمون D:میدونیم خیلی سریع از مباحث پریدم ولی نمی شد توی یه پست تموم یه کتابخونه رو یاد داد و صرفا هدف منم این نیست هدفم آشنایی با این کتابخونه پر کاربر هست که فکر میکنم تا اینجا یه دید نسبتا خوبی پیدا کردید و بعد از اینجا میتونید تصمیم بگیرید که برید سمتش یا نه ...مرسی که تا اینجا خوندید ! :)