آموزش رایگان فلسک در 30 روز
سلام وقتتون بخیر! امیدوارم حالتون عالی باشه. توی این مقاله آموزشی یعنی آموزش رایگان فلسک میخوایم با هم فلسک کار کنیم. این آموزشها نمیدونم چند قسمت میشه ولی همشون رو میذارم توی فهرست زیر که بتونید راحتتر بهشون دسترسی پیدا کنید. فلسک یه فریمورک پایتون هستش برای توسعه وب که وبسایتهای بزرگ و معروفی ازش استفاده میکنن مثلا پینترست، نتفلیکس، توییچ و… پس اگر فلسک رو بتونید خوب و حرفهای یاد بگیرین میتونید باهاش کارای بزرگی بکنید!
این مجموعه آموزشی یه پیشنیاز داره، شما باید پایتون رو بلد باشین! یعنی از صفر تا شیگرایی. اگر دوست داشتین پایتون رو اصولی و کامل یاد بگیرین بهتون دوره کامل پایتون (کلیک کنید) رو پیشنهاد میکنم.
روز اول: نصب و راه اندازی
در اولین روز از آموزش رایگان فلسک ما نیاز داریم که فلسک رو نصب کنیم. امیدوارم که پایتون و VsCode (یا حداقل یه کدادیتور دیگه) رو نصب داشته باشین. بعدش این مراحل رو انجام بدین:
یک: ما اول از همه باید یه محیط مجازی بسازیم. پس توی ترمینال بنویسید:
اون venv دومی اسم محیط مجازیتون هست؛ میتونید هر چیزی که دوست داشتین بذارین. ولی به نظرم دست نزنید!
دو: بعد از اینکه محیط مجازی رو ساختین باید فعالش بکنید. با توجه به سیستمعاملتون یکی از این دستورات رو بایستی بزنید:
سه: حالا باید فلسک رو نصب کنید. که سه روش داریم. روش عادی اینه که بنویسید:
اگر به مخازن pypi دسترسی ندارین میتونید از یه mirror ایرانی استفاده کنید. به این شکل:
اگر بازم نشد (یا مثلا اینترنت نداشتین!) میتونید آفلاین نصب کنید. چطوری؟ اول از سایت آی کد آکادمی دانلود کنید (ببخشید یه کم قدیمیه!) و پوشه رو اکسترکت کنید و با ترمینال برین داخلش و بنویسید:
خب تبریک میگم! شما تونستین فلسک رو نصب کنید! اگر خواستین تست کنید که فلسک نصب شده یا نه توی ترمینال بنویسید:
اگر نسخه فلسک نصب شده رو بهتون نشون داد، یعنی فلسک نصب شده و همه چی آرومه ما چقدر خوشبختیم 🙂
حمایت از این مجموعه آموزشی 💖
این مجموعه آموزشی به رایگان در اختیار شما قرار داده شده ولی اگر دوست داشتین همیشه میتونید از من حمایت کنید. با خریدن یه قهوه برام! لینک حمایت مالی از آقای ربات (40 هزار تومان به بالا)
روز دوم: مثال سلام دنیا!
اگر فلسک رو توی محیط مجازی نصب کردین، محیط مجازی رو فعال کنید و یه پوشه بسازین و توش یه فایل (مثلا به اسم app.py) با ویرایشگر کدتون باز کنید. امروز میخوایم اولین مثال رو ببینیم! توی برنامهنویسی همیشه اولین مثال، مثال معروف سلام دنیا هستش! یعنی کاری کنیم که توی اون پلتفرمی که داریم توش کد مینویسیم، عبارت سلام دنیا رو ببینیم. پس اول از همه باید فلسک رو ایمپورت کنیم:
بعدش باید یه اپ (یه شی از کلاس Flask) بسازیم. پس فعلا حفظی طور بنویسید:
توی فلسک به مسیرهای مختلف یک وبسایت میگن route و ما برای تعریف اولین مسیر باید از دکوراتوری به همین اسم استفاده کنیم:
اون / یعنی صفحه اول وبسایت؛ کلا اینطوری حفظ کنید که مسیرها توی فلسک با / شروع میشن. خب اگر جلوش هیچی نباشه میشه اولین صفحه وبسایت. زیر همین دکوراتور تابعی که میخواین توی صفحه اول call بشه رو باید بنویسید. من مینویسم:
و بعدش باید چک کنیم که آیا این ماژول (این فایل پایتونی) داره مستقیم اجرا میشه؟
حالا اگر اینطوریه پس باید برنامه رو اجرا کنیم. پس به جای اون سه نقطهها بنویسید:
شکل کلی برنامه:
و حالا برین توی ترمینال بنویسید:
اگر اسم فایلتون app.py نیست بدیهیه که باید اسم مال خودتون رو بنویسید! حالا توی ترمینال یه آدرسی نوشته که 127.0.0.1 و… داره! اونو کپی کنید توی مرورگر و باید مقدار Salam Donya رو توی صفحه اول ببینید. اگر دیدین یعنی دیری ری دین! مثال سلام دنیا رو با موفقیت اجرا کردین. این همه از روز دوم آموزش رایگان فلسک…
حمایت از این مجموعه آموزشی 💖
این مجموعه آموزشی به رایگان در اختیار شما قرار داده شده ولی اگر دوست داشتین همیشه میتونید از من حمایت کنید. با خریدن یه قهوه برام! لینک حمایت مالی از آقای ربات (40 هزار تومان به بالا)
روز سوم: سلام دنیا پرو پلاس!
روز دوم که مثال سلام دنیا رو اجرا کردیم، یه دستوری زدیم به اسم .run() همین الان بهتره بدونید که توی این دستور میشه این پارامترها رو تنظیم کرد:
هاست و پورت که مشخصه (ولی خب اینا رو ننویسید فعلا!) ولی دیباگ خیلی مهمه. دیباگ اگر True باشه. هر تغییری توی کد به وجود میارین سریع شناسایی میشه و نیاز نیست که برنامه رو از اجرا دربیارین و دوباره اجرا کنید، فقط کافیه صفحه رو ریلود کنید. همچنین اگر دیباگ True باشه، خطا اگر بگیرین بهتر و بیشتر راهنماییتون میکنه.
حالا بیاین مثال سلام دنیا رو یکم پیشرفتهتر کنیم! اول که میتونید از تگهای HTML استفاده کنید مثلا:
اینو اگر اجرا کنید میبینید که سلام دنیا بزرگتر شده و اومده وسط صفحه! نکته بعدی اینکه ما میتونیم دو تا مسیر رو بدیم به یه تابع! یعنی کاربر دو جا رفت، بازم همین تابع اجرا بشه. ببینید:
الان کاربر اگر بره توی این دو مسیر، یه چیز میبینه:
حالا میخوایم وبسایت ما یه مسیر دیگه داشته باشه که بتونیم قیمت دلار رو توش ببینیم! برای این کار اول از همه باید پکیج قیمت رو نصب کنیم. اگر اینترنتها اوکی هستش توی ترمینال بنویسید:
اما اگر اختلال و محدودیت وجود داره از اینجا پکیج قیمت رو دانلود کنید و بعدش اکسترکت کنید و برین داخل پوشه و بنویسید:
بعدش بالای فایل app.py اینو ایمپورت کنید. به این شکل:
حالا یه صفحه جدید بسازین:
بعدش تابع رو بنویسید:
و همین! کاری نداریم که پکیج من (قیمت) چطوری کار میکنه! خیلی هم مهم نیست و اصلا بحث این آموزش نیست. فقط بدونید که اون بیوتی رو اگر True بذارین قیمت دلار رو سه تا سه تا جدا میکنه و خواناییش بهتره! و برای کسایی که یکم زیادی تازهکار هستن باید بگم که این تابع و مسیرش باید قبل از اون شرط if main==و … باشه ها…
حالا اگر برنامه رو اجرا کنید و برین به /dollar میبینید که عه! قیمت دلار رو زد! بسه 🙂 بریم روز چهارم…
حمایت از این مجموعه آموزشی 💖
این مجموعه آموزشی به رایگان در اختیار شما قرار داده شده ولی اگر دوست داشتین همیشه میتونید از من حمایت کنید. با خریدن یه قهوه برام! لینک حمایت مالی از آقای ربات (40 هزار تومان به بالا)
روز چهارم: کار با route ها..!
امروز میخوایم یکم بیشتر با route ها یا همون مسیرهای وبسایت توی فلسک کار کنیم. ما در واقع دو نوع مسیر داریم! مسیرهای معمولی و مسیرهایی که مبدل دارن! حالا مبدل چیه؟ مبدل یه چیزیه که ما مینویسیم و کاربر ورودی میده (توی آدرس) و اون تبدیل میشه به ورودی! برای همون بهش میگن مبدل.
در مورد مسیرهای معمولی ما مثال دیدیم ازش. ولی یه نکتهای میخوام بگم که جدیده. اینو ببینید:
بلی! ما میتونیم متدها رو تعیین بکنیم. مثلا اگر متد رو فقط POST بذاریم دیگه نمیشه اون صفحه رو آدرسش رو وارد کرد و رفت داخلش! در مورد متدها بعدا بیشتر صحبت میکنیم ولی این متدها (GET و POST) شیوههای مختلف درخواست زدن به مسیرها هستن. GET برای دیدن محتوای وب استفاده میشه و POST برای ارسال اطلاعات به سرور. البته الان خیلی ناقص توضیح دادم ولی تا همینجا اینو داشته باشین بعدا میرسیم بهش…
مسیرهای مبدل، گفتیم مسیرهایی هستن که کاربر میتونه توش ورودی بزنه. مثلا فرض کنید که میخوایم توی یه مسیر، اسم کاربر رو بگیریم که بعد بتونیم بهش سلام کنیم! ببینید:
اون <user> که نوشتیم همون مبدل ماست. مثلا کاربر باید وارد کنه:
اگر اون اسم رو پر نکنید خطا میگیرین!
اگر نوع مبدل رو ننویسیم (مثل الان) رشته گرفته میشه. اما اگر بخوایم عدد بگیریم یا چیز دیگهای باید نوع مبدل رو هم انتخاب کنیم. اینطوری:
فعلا همینا یادم میاد! اگر چیز دیگه ای توی داکیومنت فلسک پیدا کردم اینجا اضافه میکنم. (خدایا اینترنت رو وصل کن، الهی آمین!)
حالا بیاین یه مثال هم بزنیم. مثلا دو تا عدد بگیریم و ضرب و تقسیم و جمع و تفریقش رو نشون بدیم! اینطوری میشه:
بقیهشو خودتون اضافه کنید! تگ <br> هم میره خط بعدی..
نکته خیلی مهم توی مبدلها اینه که هر چی اسمشون رو میذاریم، همون اسم باید ورودی تابع باشه. مثلا این غلطه و خطا میده:
فعلا تا همینجا سیخ سیخ کنید و برنامههای مختلف بنویسید تا برسیم به روز پنجم 🙂
حمایت از این مجموعه آموزشی 💖
این مجموعه آموزشی به رایگان در اختیار شما قرار داده شده ولی اگر دوست داشتین همیشه میتونید از من حمایت کنید. با خریدن یه قهوه برام! لینک حمایت مالی از آقای ربات (40 هزار تومان به بالا)
روز پنجم: کار با تمپلیت ها
امروز میخوایم یاد بگیریم چطور میشه به جای اینکه یه رشته رو return کنیم، بیایم و یه صفحه وب رو به کاربر نشون بدیم. برای اینکار باید در کنار app.py (یا اسم برنامهتون) یه پوشه بسازین به اسم templates و توش یه صفحه وب درست کنید مثلا اینطوری:
اسمشو بذارین home.html و حالا میخوایم این صفحه رو وصل کنیم به مسیر اصلی وبسایت. باید تا الان فهمیده باشین به فایلهای html توی فلسک (و البته جنگو!) میگن تمپلیت! و برای نشون دادن تمپلیتها یه تابعی هست توی فلسک به اسم render_template که باید ایمپورتش کنید:
و اینطوری میشه ازش استفاده کرد:
یعنی مثلا اگر چنین کدی توی app.py داشته باشین:
و کنار همین فایل یه پوشه به اسم templates داشته باشین ( به اون s آخرش دقت کنید) بعدش اگر این فایل رو باز کنید توی صفحه اول وبسایت میبینید که فایل home.html نمایش داده میشه! خیلی زیبا شد نه؟
حمایت از این مجموعه آموزشی 💖
این مجموعه آموزشی به رایگان در اختیار شما قرار داده شده ولی اگر دوست داشتین همیشه میتونید از من حمایت کنید. با خریدن یه قهوه برام! لینک حمایت مالی از آقای ربات (40 هزار تومان به بالا)
روز ششم: ارسال داده به تمپلیت
وقتی از تمپلیت استفاده نمیکردیم خیلی راحت میشد دیتا رو با یه استرینگ با f-string مخلوط کرد و به کاربر نشون داد. اما حالا چطور میشه؟! حالا که داریم از تمپلیتها استفاده میکنیم؟ اینجا ما باید از موتور jinja2 استفاده کنیم. جینجا یه موتور تمپلیت هستش که ما میتونیم باهاش داخل تگهای html کد بنویسیم! و ارتباط بین بکاند و فرانتاند رو برقرار کنیم. مثال دیروز یادتونه؟ یه مسیر خیلی ساده داشتیم:
بیاین به این تغییرش بدین:
اینجا ما یه متغیر به نام name و با مقدار ali ارسال کردیم به home.html… حالا اگر صفحه رو رفرش کنید هیچ تغییری حس نمیکنید! خب بایدم نکنید! چون هنوز ازش استفاده نکردیم… توی jinja2 برای نشون دادن مقدار یک متغیر از {{}} استفاده میکنیم. مثلا توی تمپلیت دیروز اگر بخوایم اون name رو استفاده کنیم اینطوریه:
خط 10 رو دقت کنید. حالا اگر همه چی رو ذخیره کنید و برنامه رو اجرا کنید میبینید که توی صفحه اصلی به مقدار اون متغیری که ساختین سلام میکنه! اگر یه وقت خواستین یه چیز دیگه ارسال کنید اینطوریه:
اونوقت میتونیم از {{ age }} هم استفاده کنیم. (راستی این فاصلهها که میذارم برای قشنگیه! تاثیری توی کد نداره!
پس تا الان فهمیدیم که توی render_template سمت چپی، اسمی هستش که باید توی تمپلیت استفاده کنیم و سمت راستی مقداری هستش که توی بخش بکاند اعتبار داره. پس اینو ببینید:
توی render_template اون name سمت چپی، چیزیه که ساختیم تا توی تمپلیت ازش استفاده کنیم و name سمت راستی داریم میگیم که مقدارش مساوی با مقدار متغیر name توی بکاند باشه. امیدوارم گیج نشده باشین! حالا اگر شدینم که دیگه کار از کار گذشته! بعدا درست میشه…!
حمایت از این مجموعه آموزشی 💖
این مجموعه آموزشی به رایگان در اختیار شما قرار داده شده ولی اگر دوست داشتین همیشه میتونید از من حمایت کنید. با خریدن یه قهوه برام! لینک حمایت مالی از آقای ربات (40 هزار تومان به بالا)
روز هفتم: حلقه و شرط در تمپلیت
جینجا فقط برای نشون دادن دادهها توی تمپلیت نیست. بلکه میتونیم توش حلقه یا شرط بنویسیم! مثلا اگر به تمپلیت یه لیست بفرستیم چی میشه؟! ببینید:
حالا آیا درسته ما توی تمپلیت بنویسیم:
؟ نه دیگه! اینطوری خود لیست رو میاره میذاره جلوی Hello و این زشته! خیلی زشته. خیلی خیلی زشته! برای همین باید یه حلقه بنویسیم. دستورات (مثل حلقه و شرط) با {% %} نوشته میشن. مثلا حلقه اینطوریه:
برای اون مثال لیست names اینطوری میشه:
حواستون به اون endfor باشه. شرط هم همینطوریه. مثلا میتونیم بگیم اگر لیست خالی نبود این حلقه اجرا بشه. اگر لیست خالی بود بگه هیچی توی لیست نیست! فقط بازم یادتون نره برای شرط باید endif بنویسیم.
حالا بپرین برین توی کد و لیست رو خالی کنید. بعدش میبینید که میگه توش هیچی نیست! اینم از شرط و حلقه. با همینا خوش باشین فعلا تا بریم به روز هشتم…
حمایت از این مجموعه آموزشی 💖
این مجموعه آموزشی به رایگان در اختیار شما قرار داده شده ولی اگر دوست داشتین همیشه میتونید از من حمایت کنید. با خریدن یه قهوه برام! لینک حمایت مالی از آقای ربات (40 هزار تومان به بالا)
روز هشتم: ارسال دیکشنری به تمپلیت
آموزشهای قبلی متغیر و لیست رو ارسال کردیم به تمپلیت. رفتار عجیب غریبی هم ندیدیم. منظورم اینه که متغیر یا لیست اونور (تمپلیت) هم به همون شکل استفاده میشد. اما اگر ما یه دیکشنری رو بفرستیم به سوی تمپلیت، اونور این دیکشنری به حالت یه شی در نظر گرفته میشه که یه سری اتربیوتها داره. یعنی چی؟ مثلا اینو ببینید:
یه دیکشنری ساختیم به اسم data و گفتیم توی template اگر گفتیم person منظورمون همون چیزمیزای داخل data هستش. حالا توی تمپلیت اگر بخوایم به کلید name توی دیکشنری اشاره کنیم باید از . (دات) استفاده کنیم. شبیه شیگرایی توی پایتون میشه. مثلا ببینید:
دیدین؟ مثلا person.name یا person.age و از این سوسول بازیا. درس امروز تمومه فقط میخوام یه نکتهای رو بگم. سعی کنید همیشه کدها رو بنویسید! یه بار خودتون همونو بنویسید. یا یکم تغییر بدین و بنویسید. با خودتون نگین “چشمی دارم نگاه میکنم دیگه! نیازی به اجرا کردن نیست. کار میکنه!” بنویسید! به من اعتماد کنید و بنویسید.. بعدا ازم تشکر میکنید!
حمایت از این مجموعه آموزشی 💖
این مجموعه آموزشی به رایگان در اختیار شما قرار داده شده ولی اگر دوست داشتین همیشه میتونید از من حمایت کنید. با خریدن یه قهوه برام! لینک حمایت مالی از آقای ربات (40 هزار تومان به بالا)
روز نهم: پروژه سازنده فاکتور!
خب میرسیم به روز نهم! امروز میخوایم یه پروژه بسازیم! یه پروژه که خریدهای ما رو از یه فایل متنی میخونه و برامون فاکتور قابل چاپ میسازه! ما یه فایل متنی داریم به اسم buys.txt که محتواش اینطوریه:
حالا یه فایل پایتونی داریم که اول از همه فلسک رو توش ایمپورت میکنیم و یه app میسازیم:
بعدش یه تابع میخوایم که فایلی که بهش میدیم رو باز کنه و محتویاتش رو به شکل دیکشنری دربیاره:
این پایتون پایه هستش! امیدوارم بلد باشین. حالا مسیر اصلی رو بسازین و توش فایل buys رو بدین به این تابع و خروجی رو بفرستین به تمپلیت:
یه کار اضافه هم کردیم. اومدیم جمع تمام محصولات رو هم فرستادیم و همچنین دستورات اجرایی فایل پایتون رو گذاشتیم. حالا توی تمپلیت یه جدول میسازیم (جدول ساختن توی html خیلی آسونه بخونید درموردش) و به ازای آیتمهایی که توی data وجود داره یه ردیف میسازیم و محتویات رو قرار میدیم:
پایین جدول هم جمع کل رو گذاشتیم. همچنین یه دکمه ساختیم که روش اگر کاربر کلیک کنه، میاد که اون فاکتور رو چاپ کنه یا خروجی pdf بگیره! تگهای HTML رو خیلی توضیح نمیدم چون خیلی واضحه که چی هستن. یا خودتون یکم دستکاری کنید میفهمید یه تگ چیکار میکرده و… امیدوارم که با این پروژه هر چیزی که تا الان یاد گرفتیم رو مرور کرده باشین.
حمایت از این مجموعه آموزشی 💖
این مجموعه آموزشی به رایگان در اختیار شما قرار داده شده ولی اگر دوست داشتین همیشه میتونید از من حمایت کنید. با خریدن یه قهوه برام! لینک حمایت مالی از آقای ربات (40 هزار تومان به بالا)
روز دهم: ارث بری در تمپلیت
تصور کنید یه فایل html داریم، این فایل html یه بخش هدر داره، یه بخش منو، یه بخش فوتر، یه بخش و… این بخشها تقریبا توی اکثر صفحات تکرار میشه و شایسته نیست (اوهع!) که هی اینا رو کپی پیست کنیم. بهتره اینا رو یه جایی بنویسیم و هر بار که خواستیم ازشون استفاده کنیم. زیبا میشه نه؟ خوشبختانه اینو میشه پیادهسازی کرد. با دستور block و extends. ببینید این صفحه اصلی سایت اگر هست:
میایم یه صفحه میسازیم به اسم base.html و چیزایی رو توش میذاریم که قراره هی تکرار بشن و چیزایی که قراره تغییر کنن رو توی {% block name %} میذاریم:
و بعد توی صفحه اصلی میایم اینو وارد میکنیم (با دستور extends) و چیزایی که قراره توی block ها بذاریم رو جایگزین میکنیم. مثلا توی صفحه اصلی:
به اون دستور extends دقت کنید! مثل import توی پایتون هستش. حالا اگر بخوایم یه صفحه دیگه داشته باشیم:
اینم از این. خوش باشید تا روز بعدی!
حمایت از این مجموعه آموزشی 💖
این مجموعه آموزشی به رایگان در اختیار شما قرار داده شده ولی اگر دوست داشتین همیشه میتونید از من حمایت کنید. با خریدن یه قهوه برام! لینک حمایت مالی از آقای ربات (40 هزار تومان به بالا)
روز یازدهم: فایل های استاتیک
امروز میخوام بهتون یاد بدم چطوری میشه عکس، فایلهای CSS/JS رو توی فایل HTML آدرس دهی کرد. اول از همه باید بیاین توی پوشه ریشه (root) پروژه تون کنار پوشه templates یه پوشه بسازین به اسم static و بعدش داخل اون پوشه چند پوشه جدا images، css، js و … بسازین. حالا اگر توی تمپلیت قرار باشه به فایل css وصل بشه، در حالت عادی آدرس اینطوریه:
اگر بخوایم توی فلسک آدرس دهی کنیم، یه تابعی هست توی jinja به اسم url_for که میاد آدرس رو برای ما میسازه. نحوه استفادهاش اینطوریه:
برای فایلهای جاوا اسکریپت یا عکس هم به همین ترتیب میشه استفاده کرد. مثلا برای عکس اگر داریم:
میشه:
خب اینم از این! خوش باشین تا بعد…
حمایت از این مجموعه آموزشی 💖
این مجموعه آموزشی به رایگان در اختیار شما قرار داده شده ولی اگر دوست داشتین همیشه میتونید از من حمایت کنید. با خریدن یه قهوه برام! لینک حمایت مالی از آقای ربات (40 هزار تومان به بالا)
روز دوازدهم: ریکوئست GET در فلسک
کاربری که داره با سایت شما کار میکنه، دائم درخواست (request) ارسال میکنه و پاسخ (response) میگیره. پاسخ که مشخصه به هر حال یه صفحه وبی، یه پیغامی چیزی بهش نشون داده میشه. در مورد درخواست، ما دو نوع درخواست داریم، GET و POST که امروز میخوایم با GET کار کنیم.
درخواست با متد GET: توی این متد کاربر اطلاعاتی که قراره برای ما بفرسته رو توی URL میفرسته. مثلا فرض کنید یه مسیر داریم که میخوایم اسم کاربر رو بگیریم. اینو میشد با مبدلها توی روز چهارم یاد گرفتیم اما اینبار میخوایم مسیر سایت ما اینطوری باشه:
توی متد GET اگر بخوایم پارامتری ارسال بشه باید اول یه ؟ بذاریم و بعدش پارامترها رو به شکل key=value ارسال کنیم. برای دریافتش توی بخش فلسک از request.args.get استفاده میکنیم البته باید request رو هم ایمپورت کرده باشیم:
حالا اگر برین این مسیر و چیزی ارسال نکنید، خب name دریافت نمیشه و میگه سلام مهمان اما اگه این پارامتر رو ارسال بکنید به اون اسمی که دادین سلام میکنه. این روش ارسال اطلاعات، امن نیست. چون همه چی توی URL دیده میشه. برای همین از این روش فقط برای مواقعی ارسال میشه که درخواست شامل اطلاعات حساس نباشه. مثلا فرض کنید یه سایت فروشگاهی داریم، کاربر میخواد محدوده قیمت رو مشخص کنه، برند رو مشخص کنه و… حالا این URL رو برای یه دوست دیگهاش میفرسته که با همون شرایط، محصولات رو ببینه. اینها همه با متد GET هست. همچنین توی بخش فرمها توی HTML ما میتونیم متد ارسال اطلاعات فرم رو GET بذاریم و بعدش اطلاعات توی URL ارسال میشن. مثلا این فرم رو ببینید:
البته امیدوارم HTML رو تا حدی بلد باشین ولی اینجا دو تا فیلد ساختیم که اسماشون به ترتیب min_price و max_price هستش و وقتی کاربر روی دکمه submit کلیک کنه اینا با متد GET ارسال میشن به مسیر /search و بعد توی فلسک میتونیم اینطوری دریافت کنیم:
اینو فعلا کار کنید تا بعدش بریم سراغ متد POST، جایی که اطلاعات حساس ارسال میشن…
حمایت از این مجموعه آموزشی 💖
این مجموعه آموزشی به رایگان در اختیار شما قرار داده شده ولی اگر دوست داشتین همیشه میتونید از من حمایت کنید. با خریدن یه قهوه برام! لینک حمایت مالی از آقای ربات (40 هزار تومان به بالا)
روز سیزدهم: ریکوئست POST در فلسک
روز قبل با متد GET آشنا شدیم و گفتیم که ارسال درخواست با این متد برای مواقعی هست که اطلاعات حساس ارسال نمیشه. امروز میخوایم با POST کار کنیم. توی ریکوئست با متد POST دیگه دیتاها توی URL ارسال نمیشن و توی بدنه ارسال میشن به بکاند برای همین مناسب ارسال اطلاعات حساس هستش. مثلا فرم لاگین، فرم ثبت سفارش، فرم ثبتنام و… متد GET چون اطلاعات توی URL ارسال میشد، میتونستیم فرم نداشته باشیم اما برای استفاده از متد POST باید حتما یه فرم داشته باشیم. مثلا اینطوری ( برای کوتاهتر شدن فقط بخش body رو گذاشتم):
میبینید که متد post هستش (حروف کوچیک بنویسید هم کار میکنه) حالا اگر بخوایم توی فلسک username و password رو بگیریم، باید از reuqest.form استفاده کنیم (بازم دقت کنید که import شده باشه) و مقدار name این input ها رو بدیم.
البته اینو بگم که لاگین کردن اینطوری انجام نمیشه! چون خیلی ناامنه. بعدا اینو توی بخش احراز هویت یاد میگیریم. فعلا فقط میخوایم ببینیم چطوری میشه اطلاعات بین فرانتاند و بکاند رد و بدل بشه…
حالا که متدها ارسال درخواست رو شناختیم، شاید براتون سوال شده باشه که آیا میشه یه مسیر، هم درخواست POST قبول بکنه و هم GET؟ بله میشه. اینطوریه که ما اول باید نوع درخواست رو چک کنیم. مثلا برای همین مسیر لاگین:
و بدین ترتیب میتونیم بگیم که اگر کاربر رفته بود توی url آدرس مسیر لاگین رو نوشته بود (یعنی متد GET بود) بیا و صفحه لاگین رو نشون بده اما اگر فرم لاگین رو پر کرده بود و روی دکمه سابمیت کلیک کرده بود (یعنی متد POST بود) بیا و اطلاعات فرم رو بگیر و پردازش کن…
حمایت از این مجموعه آموزشی 💖
این مجموعه آموزشی به رایگان در اختیار شما قرار داده شده ولی اگر دوست داشتین همیشه میتونید از من حمایت کنید. با خریدن یه قهوه برام! لینک حمایت مالی از آقای ربات (40 هزار تومان به بالا)
روز چهاردهم: کار با Session در فلسک
خب امروز میخوایم با سیشنها کار بکنیم. سیشن یا Session یک روش برای ذخیره موقتی اطلاعات کاربر توی سرور هستش. زمانی که کاربر وارد یک وبسایت میشه، یک سیشن براش در نظر گرفته میشه و بعدا اگر نیاز بود اطلاعاتی داخلش ذخیره میشه. مثل چی؟ مثلا برای وبسایت فروشگاهی، سبد خرید یه مثال خوب از سیشن هستش. چیزهایی که داخل سبد خریده، موقتی هستن و نیازی نیست توی دیتابیس ذخیره بشه برای همین توی سیشن ذخیره میشه و وقتی سفارش انجام شد (یا نشد) اون اطلاعات از بین میرن. یا مثلا در مورد فرمهای چند صفحهای وقتی از یه صفحه به صفحه دیگهای میریم اطلاعات فرم قبلی در قالب سیشن ارسال میشه به فرم بعدی و وقتی در نهایت کل صفحات فرم ثبت شدن، اون سیشن از بین میره.
سیشن در سمت سرور ایجاد و ذخیره میشه و یک Session ID به مرورگر کاربر ارسال میشه. پس کاربر نمیتونه اون رو خارج از پنل خودش، ویرایشش بکنه. برای همین امنیت سیشنها بالاتر از کوکیها (بعدا صحبت میکنیم در موردشون) هستش.
برای استفاده از سیشنها توی فلسک باید از session استفاده کنیم پس اول از همه ایمپورت میکنیم:
اون چیزهای دیگه که ایمپورت کردیم رو موقع استفادهشون میگم چی هستن. فعلا کار مهمتری داریم! الان باید یه کلید مخفی بسازیم. این کلید برای حفظ امنیت هستش:
من یه چیز الکی گذاشتم! ولی خب مثل رمز هستش دیگه. سعی کنید تا میتونید پیچیده بذارینش! حالا فرض کنید یه مسیر داریم برای لاگین که یه فرم نشون میده و یوزرنیم میگیره (خیلی بیسیک فرض کنید چنین چیزی هست):
سیشن ماهیتش دیکشنری هستش. میایم یه کلید میسازیم و value اون رو مساوی چیزی که میخوایم قرار میدیم. توی این مثال ما یوزرنیم رو از فرم لاگین گرفتیم و توی سیشن ذخیره کردیم. بعدش میخوایم کاربر رو هدایت کنیم به یه مسیری. یعنی وقتی این کار انجام شد کاربر کجا بره؟ برای اینکار باید از redirect استفاده کنیم. ریدایرکت یه مسیر میگیره، ما به جای اینکه اسم اون مسیر رو بنویسیم میایم از url_for استفاده میکنیم. اینطوری اگر آدرس سایت عوض بشه، نیازی نیست بیایم این تابع رو تغییر بدیم. توی url_for هم فقط آدرس route رو مینویسیم. خب حالا کاربر میره به این مسیر:
اینجا میایم چک میکنیم اگر کلیدی با عنوان username توی دیکشنریِ سیشن وجود داشت، مقدارش رو میگیریم و بهش خوش آمد میگیم. اما اگر کاربر لاگین نکنه و بیاد توی این مسیر، بهش میگه شما لاگین نکردین! این سیشن ذخیره شده. یعنی چی؟ یعنی اگر برنامه رو ببندیم و مستقیم بریم توی مسیر /profile میبینیم که عه! هنوز اسم ما رو یادشه! خب حالا چیکار کنیم که یادش بره؟ میایم یه مسیر logout میسازیم و توش میگیم اون سیشن پاک بشه. پاک کردن توی دیکشنری چی بود؟ pop … :
اینم از روز چهاردهم آموزش رایگان فلسک، مدیریت، پاک کردن، اضافه کردن، سیشن در فلسک…
حمایت از این مجموعه آموزشی 💖
این مجموعه آموزشی به رایگان در اختیار شما قرار داده شده ولی اگر دوست داشتین همیشه میتونید از من حمایت کنید. با خریدن یه قهوه برام! لینک حمایت مالی از آقای ربات (40 هزار تومان به بالا)
روز پانزدهم: کار با Cookie در فلسک
توی روز قبل با سیشنها کار کردیم، امروز میخوایم با کوکیها کار کنیم. کوکیها فایلهای کوچیکی هستند که توسط سرور توی مرورگر کاربر ذخیره میشن. این فایلها میتونن حاوی اطلاعاتی باشن که برای دفعات بعدی که کاربر به وبسایت سر میزنه استفاده بشه. هدف اصلی کوکیها اینه که سرعت بارگذاری وبسایت بیشتر بشه چون وقتی یه سری اطلاعات سمت کاربر ذخیره بشه، دیگه برای اونا نیاز نیست سرور کاری بکنه و در نتیجه سرعت وبسایت یا وباپلیکیشن بیشتر میشه.
کوکیها رو احتمالا خیلی جاها دیدین! مثلا وقتی تنظیمات یه سایت رو میذاریم روی دارک مود، دفعه بعدی هم دارک مود میمونه. این تنظیم توی کوکی ذخیره میشه تا مرورگر وقتی میخواد سایت رو بارگذاری بکنه، دارک مود رو بارگذاری بکنه و لایت مود رو نه! یا مثلا شاید اگر الان اینترنت گوشی رو خاموش کنید و اینستاگرام رو باز کنید میبینید یه سری پستها رو میشه دید! یه سری چتهای تلگرام رو میشه دید و خوند یا حتی یه سری ویسها و ویدیوها رو میشه دید (که قبل دانلود کردین). خب اینا تماما مثالهایی از کوکیها هستن.
تفاوت مهم: کوکی سمت کاربر هستش، سیشن سمت سرور!
برای سیشنها دیدیم که سمت سرور ساخته و ذخیره میشن و به مرورگر فقط یه سیشن آیدی ارسال میشه. اما کوکی سمت کاربر ساخته میشه و وقتی کاربر برای دفعات بعدی میخواد وارد اون سایت بشه، کوکیها هم همراه درخواست کاربر ارسال میشن و اون سایت با اون کوکیها بارگذاری میشن.
برای پیادهسازی مثالی از کوکی، ما به make_response نیاز داریم:
حالا اگر یه فرم لاگین داشته باشیم که به مسیر /login وصل باشه میتونیم یوزرنیم رو بگیریم و کاربر رو بفرستیم به صفحه پروفایلش و کوکی رو با set_cookie تنظیم کنیم:
حالا برای گرفتن کوکی از request.cookies استفاده میکنیم:
حالا اگر بخوایم کوکی رو دلیت کنیم از delete_cookie استفاده میکنیم:
تفاوتهای کوکی و سیشن:
شاید اینجا که رسیده باشین براتون سوال شده باشه که چه فرقی بین سیشن و کوکی وجود داره؟! ما با هر دو یه کار کردیم که! اصلا از کجا بدونیم کِی از کوکی استفاده کنیم و کِی از سیشن؟ اول از کوکی شروع میکنم:
کوکیها سمت کاربر ساخته میشن، کمتر امن هستن و کاربر میتونه دستکاری بکنه، اندازهاش محدوده معمولا در حد کیلوبایت و معمولا برای تنظیماتی ساخته که کمک کنه مرورگر دفعه بعدی بهتر و سریعتر سایت رو بارگذاری بکنه. کوکیها عمرشون از چند ثانیه تا چندین سال هستش
سیشنها سمت سرور ساخته میشن، امنتر از کوکیها هستن، اندازهشون میتونه خیلی بیشتر باشه بستگی به تنظیماتی داره که توی سرور انجام میشه. سیشنها عمر محدودتری دارن معمولا تا وقتی مرورگر بسته بشه یا تنظیماتی که سمت سرور تنظیم شده
حمایت از این مجموعه آموزشی 💖
این مجموعه آموزشی به رایگان در اختیار شما قرار داده شده ولی اگر دوست داشتین همیشه میتونید از من حمایت کنید. با خریدن یه قهوه برام! لینک حمایت مالی از آقای ربات (40 هزار تومان به بالا)
روز شانزدهم: ساخت پایگاه داده در فلسک
امروز میخوایم به شکل رسمی کار با دیتابیس رو شروع کنیم! توی فلسک معماری MVT به شکل پیشفرض وجود نداره ولی ما میتونیم شبیه چیزی که توی Django هست، توی فلسک هم پیادهسازی بکنیم. معماری MVT مخفف سه چیزه:
Model
View
Template
مدل، بخشی هستش که با دیتابیس سر و کار داره و ماهیتش کلاس هست، ویوو همون توابعی هستند که تا الان مینوشتیم و به مسیرهای مختلف وصل بودن و تمپلیت فایلهای HTML هستند. همچنین یه چیزی داریم به اسم ORM یعنی Object Reletional Mapping یه ابزاری هستش که ما میایم باهاش به زبان پایتون، دستورات (یا کوئری) های دیتابیس رو مینویسیم. فایدهاش چیه؟ فایدهاش اینه که ما اگر یه روزی دیتابیس پروژه رو عوض کردیم، دیگه لازم نیست کوئریهاش رو هم عوض کنیم. چون ORM میاد همون دستورات ما رو به کوئریهای دیتابیس جدید تبدیل میکنه. (چون دیتابیسهای مختلف مثل sql-sqlite-postgresql-oracle و… دستوراتشون فرق داره!)
توی جنگو ما Django-ORM داریم، خوشبختانه این ابزار توی فلسک هم هست به اسم flask-sqlalchemy که باید با دستور زیر نصب بشه:
اگر برای نصب مشکل دسترسی به مخازن pypi دارین، اینجا رو چک کنید چون مفصل توضیح دادم چیکار کنید.
حالا برای اینکه پروژه ما استاندارد باشه، مدل رو مستقیما توی فایل اصلی برنامه نمینویسیم. به جاش یه فایل درست کنید به اسم models.py کنار برنامه اصلی (مثلا app.py) و توش باید SQLAlchemy رو ایمپورت کنیم. این یه کلاس هستش. باید ازش یه شی بسازیم که در اصل میشه دیتابیس ما:
گفتیم ماهیت مدلها کلاس هستن. مدل چیه اصلا؟ مدل اون نقشهای هستش که ما میایم میگیم بر این اساس باید دیتاها ذخیره بشن. مثل جدولها توی اکسل میمونن، ما میایم یه جدول میسازیم، میگیم این ستونها رو داره و قراره دیتاها به این ستونها اضافه بشن. هر دیتا میشه یه شی از این کلاس. مثلا مدل زیر رو ببینید:
ما اینجا یه مدل Student داریم که از کلاس db.Model ارثبری میکنه و سه تا ستون داره، آیدی، اسم و مدل. میبینید که نوعشون رو هم انتخاب کردیم که مثلا توی ستون id فقط میشه عدد داشت (db.integer) و برای رشته هم به همین صورت و گفتیم فقط تا 80 کاراکتر مجازه برای این ستون. ستونها میتونن نوعهای مختلفی داشته باشن که مهمتریناشون اینان:
یا چیزهای مختلف رو میشه تنظیم کرد مثلا گفتیم آیدی منحصر بفرد باشه و خودش ساخته بشه (primary_key=True) یا برای اسم و معدل گفتیم نمیشه خالی باشن (nullable=False) چیزهای دیگهای رو هم میشه شخصیسازی کرد مهمهاش:
توی این کلاس یه متد هم تنظیم کردیم به اسم repr که موقعی فراخوانی میشه که یه شی از این کلاس ساخته بشه. من گفتم هر وقت ساخته شد چاپ بشه چنین دانشجویی ساخته شد. (توی کنسول برای لاگ گیری).
حالا ما باید بیایم توی app.py و اول db و Student رو ایمپورت کنیم:
حالا یه تنظیماتی هست که باید بگیم این پروژه به کدوم دیتابیس وصل باشه، نوعش چیه؟ آدرسش کجاست؟ فعلا کپی وار بنویسید:
خط دوم رو حتما بنویسید! باعث میشه دیتابیس یه سری خطاها و warning ها که اغلب مهم نیستن رو نده و همه چی به خوبی و خوشی پیش بره! حالا که آدرس دیتابیس و اینا رو مشخص کردیم باید دیتابیس رو به برنامه بشناسونیم پس باید بنویسیم:
و درنهایت باید اون مدلها که توی models.py داریم رو توی دیتابیس بسازیم (که میشن جداول) پس باید قبل از اجرای پروژه بنویسیم:
این برنامه رو یه بار اجرا کنید و بعدش خط 2و3 توی کد بالا رو کامنت کنید! چون لازم نیست! فقط وقتی دوباره لازم میشه که توی models.py مدل جدیدی اضافه کرده باشین.
حالا اگر بعد از اجرا برین توی پوشه پروژه میبینید که یه پوشهای ساخته شده به اسم instance و توش دیتابیسی به اسم database.db وجود داره! تا همینجا بسه امروز خیلی طولانی شد خسته میشین! فردا میریم برای کارای CRUD توی دیتابیس…
حمایت از این مجموعه آموزشی 💖
این مجموعه آموزشی به رایگان در اختیار شما قرار داده شده ولی اگر دوست داشتین همیشه میتونید از من حمایت کنید. با خریدن یه قهوه برام! لینک حمایت مالی از آقای ربات (40 هزار تومان به بالا)
روز هفدهم: عملیات CRUD در فلسک
در روز هجدهم آموزش رایگان فلسک میخوایم ببینیم عملیات CRUD یا Create-Read-Update-Delete توی فلسک چطوری انجام میشه. منظور از این عملیات خیلی مشخصه. که یه سیستمی پیادهسازی بکنیم که بتونیم دادهها رو از پایگاه داده بخونیم، داده جدید بسازیم، دادههای قبلی رو ویرایش یا حذف بکنیم. مدلی که روز قبل ساختیم رو در نظر داشته باشین:
عملیات Create:
اول از ساختن شروع میکنیم. ساختن با دستور db.session.add انجام میشه. اما قبل از اون باید یه تمپلیت داشته باشیم که یه فرم توش باشه:
اینو بذارین توی یه تمپلیت مثلا add_student.html و بعدش توی ویوو باید چک کنیم که ریکئوست post بوده یا get. اگر post بوده مقدارهای name و average رو از فرم بگیریم و بعدش از مدل که یه کلاس بود باید یه شی بسازیم و در نهایت اون شی رو بدیم به db.session.add… اینطوری:
نکته: هر وقت تغییری توی دیتابیس انجام میدیم باید commit کنیم. مثلا ساختن، ویرایش کردن، حذف کردن، تغییره ولی خوندن تغییر نیست. پس فقط عملیات Read هستش که commit نداره…
و اگر ریکوئست get بود هم صفحه رو به کاربر نشون بده. یه کار اضافهای هم انجام دادم، اگر درخواست post باشه، اطلاعات گرفته میشه و دانشآموز ثبت میشه و بعدش باید کاربر رو هدایت کنیم به یه صفحهای. در این راستا شما میتونید کاربر رو بفرستین به صفحه اصلی (با ریدایرکت و url_for) ولی من همون صفحه add_student.html رو دوباره رندر کردم منتها یه پیغام ارسال کردم. که اگر کاربر ساخته شده بود بگه این کاربر (اسمش) ساخته شد.
عملیات Read:
حالا میخوایم توی صفحه اصلی، لیست دانشآموزان و معدلشون رو نشون بدیم. به این کار میگن Read یعنی اطلاعات رو از دیتابیس میخونیم. خوندن با Model.query.all هستش. به جای مدل باید اسم مدلتون رو بذارین. این به ما یه لیست میده که آیتمهاش دیکشنریان. این لیست رو میگیریم و میفرستیم به سمت تمپلیت:
و بعد توی تمپلیت، روی این لیست حرکت میکنیم و:
این از همه سادهتر بود!
عملیات Update:
آپدیت یعنی بهروزرسانی یا ویرایش کردن. میشه گفت از همه عملیات سختتره! چون نیاز به چند تا چیز داریم. اول اینکه توی صفحه Home بیایم برای هر شی یه لینک بسازیم که اگر کاربر روش کلیک کرد آیدی اون شی ارسال بشه به صفحه edit… اینطوری میشه این کار رو کرد:
این همون home.html هستشهاا… فقط لینک رو اضافه کردیم بهش. حالا باید این صفحه (edit) رو بسازیم. توی این صفحه ما به اون شی دسترسی داریم. یعنی میتونیم اون فرم ویرایش رو با اطلاعات فعلی اون شی پر کنیم که بعد کاربر هر کدوم رو خواست ادیت کنه (نه که کل فرم رو دوباره پر کنه):
میبینید که بخش value رو ایندفعه پر کردیم. و همچنین به بخش action دقت کنید. اونجا میشه گفت کاربر روی دکمه سابمیت کلیک کرد، کجا بره. ما بازم ارجاع میدیم به مسیر edit. حالا توی بخش edit باید مسیر رو طوری بسازیم که آیدی رو توی مبدل بگیریم یعنی:
حالا باید اطلاعات اون شی که آیدیش رو داریم رو بگیریم (داخل ویوو ادیت نوشته بشه):
اگر چنین شی وجود نداشته باشه خطای 404 میده. حالا که شی رو گرفتیم باید چک کنیم که کاربر فرم رو پر کرده و روی دکمه submit کلیک کرده؟ (ریکوئست post) یا کاربر توی home روی لینک edit کلیک کرده؟ (ریکوئست get). اگر فرم رو پر کرده که اطلاعات رو جایگزین و کامیت میکنیم:
اگر ریکوئست get هستش که باید اون صفحه فرم رو نشون بدیم. فقط شی رو هم ارسال میکنیم به تمپلیت که بعد به مقدارهای .id و .name و .average دسترسی داشته باشیم:
عملیات Delete:
آخرین عملیات، حذف هستش. حذف خیلی راحته، اگر که ویرایش رو خوب متوجه شده باشین. برای حذف اول از همه باید توی Home یه لینک بذاریم که ما رو ببره به مسیر delete (مثلا) اگر لینک بذارین درخواست get هستش ولی ما میایم و درخواست رو post میکنیم، با ساختن یه فرم کوچیک و یه دکمه سابمیت. پس شکل نهایی صفحه home اینطوری میشه:
حالا اگر کاربر روی دکمه Delete کلیک کنه اول براش میاد که R U Sure؟ (جا کم بود مجبور شدم مخفف بنویسم) بعدش آیدی اون دانش آموز رو میفرسته به بخش delete که باید اونجا بنویسیم:
تقریبا تکراری بود دیگه! اون دانشآموز رو گرفتیم ولی خب به جای ویرایش، حذفش کردیم و پایگاه داده رو کامیت کردیم. حالا نکتهای که هست اینه که اگر شما خواستین لینک بسازین برای بخش حذف (توی صفحه اصلی) اینجا باید متد این مسیر GET باشه (یا نذارین کلا)
خب اینم از این بخش. امیدوارم خسته یا گیج نشده باشین. یکم تمرین و تکرار کنید دستتون میاد. روز بعدی میبینمتون 🙂
حمایت از این مجموعه آموزشی 💖
این مجموعه آموزشی به رایگان در اختیار شما قرار داده شده ولی اگر دوست داشتین همیشه میتونید از من حمایت کنید. با خریدن یه قهوه برام! لینک حمایت مالی از آقای ربات (40 هزار تومان به بالا)
روز هجدهم: مدل های رابطهای
دو روز قبلی اومدیم خیلی انفجاری با دیتابیسها کار کردیم و آشنا شدیم! اما مسئله اینجاس که بحث دیتابیسها خیلی فراتر از اینهاست و در این آموزش نمیگنجه. ولی یه مبحث خیلی مهم دیگه که پرکاربردتر هستش رو امروز بررسی میکنیم به اسم مدلهای رابطهای. مدل چی بود؟ همون نقشههای اولیه برای ساخت و ذخیرهسازی دادهها. حالا مدلهای رابطهای، مدلهایی هستن که به هم وصلن. یه ارتباطی بینشون هست. مثلا اینستاگرام رو در نظر بگیرین. توی اینستاگرام یه کاربر (مدل کاربر) یه سری پست (مدل پست) داره. اینا به هم وصلن. مثلا کاربر میره توی پروفایل خودش، فقط پستهای خودش رو میبینه! یا میره پیج یکی دیگه، فقط پستهای اون شخص رو میبینه. اما مثلا توی اکسپلور همه پستها رو میبینه (حالا تحتِ یک سری الگوریتمهایی).
حالا یه مثال سادهتر رو توی فلسک پیادهسازی میکنیم. فرض کنید میخوایم یه سایت کتابفروشی بسازیم. توی این سایت دو تا مدل میخوایم یکی برای کتاب، یکی برای نویسنده. قبول دارین هر نویسندهای میتونه چند تا کتاب داشته باشه؟ پس اینا انگار به هم وصلن. یا یه جورایی مدل کتاب، به مدل نویسنده وابستهاس. یعنی ما مدل کتاب رو نمیتونیم بسازیم مگر اینکه نویسنده براش انتخاب کنیم. به این نوع ارتباط میگن ForeignKey و نحوه پیادهسازیش اینطوریه:
اول مدل نویسنده رو ببینید:
خب اینجا که کار خاصی نکردیم! حالا مدل کتاب که وابسته هستش رو ببینید:
به author_id دقت کنید! ما اومدیم هر کتاب رو به یه نویسنده وصل کردیم. در واقع هر کتاب آیدی نویسنده رو داره. توی این حالت اگر بخوایم یه کتاب اضافه کنیم اینطوریه:
نکته: توی بخش author_id هم میتونید خود شی یعنی author رو بدین و هم آیدی رو. ولی آیدی رو بدین بهینهتره.
حالا فرض کنید میخوایم تمام کتابهای یک نویسنده رو ببینیم. یا نویسنده یک کتاب رو ببینیم. چطوری میشه؟ روشهای مختلفی وجود داره ولی بهینهترین و حرفهایترینش اینه که ما بیایم توی هر مدل یه فیلد جدید اضافه کنیم از نوع db.relationship یعنی برای مدل نویسنده داریم:
اینطوری مثلا میتونیم بگیم author.books و تمام کتابهاشو بیاره. توی این رابطه cascade تنظیم کردیم، یعنی اگر یک نویسنده پاک شد، چه اتفاقی برای کتابهاش بیوفته. ما گفتیم که همه رو پاک کنه! برای مدل کتاب هم میتونیم بنویسیم:
و بعد میتونیم بگیم book.author و نویسنده اون کتاب رو به ما میده.
نکته2: این فقط یک نوع رابطه بود. رابطههای دیگهای هم هست مثل One-To-One یا Many-To-Many که اونا رو برین خودتون از داکیومنت مطالعه کنید!
حمایت از این مجموعه آموزشی 💖
این مجموعه آموزشی به رایگان در اختیار شما قرار داده شده ولی اگر دوست داشتین همیشه میتونید از من حمایت کنید. با خریدن یه قهوه برام! لینک حمایت مالی از آقای ربات (40 هزار تومان به بالا)
روز نوزدهم: نکات تکمیلی و طرح پروژه todo list
امروز میخوام بهتون مشق بگم! چیزی نمیخوام بهتون یاد بدم! اما قبلش یه سری نکات بگم. اولیش اینکه این چیزایی که توی این 3 روز کار با پایگاه داده دیدین، تمام مباحث نبود. حتما برین نحو پیادهسازی انواع رابطهها رو یاد بگیرین. به ORM تسلط کامل داشته باشین. در مورد کار با postgresql توی فلسک یاد بگیرین چون دیتابیس مهمی هستش. پس اینا رو سپردم دست خودتون!
و اما بریم سراغ پروژه! پروژه TodoLIST توی این پروژه شما باید بیاین برای بخش فرانت، از یه ابزار هوشمصنوعی کمک بگیرین و بگین یه تمپلیت ساده براتون بسازه که از بوت استرپ یا مثلا Tailwind استفاده کنه و توی صفحه اصلی بالاش بتونیم کار جدید اضافه کنیم، پایین از وسط دو نیمه شده باشه و یک ور کارهای انجام شده رو نشون بده و یک ور کارهای انجام شده رو. بعد این تمپلیت رو بگیرین و توی فلسک ویووهای مختلف رو بنویسید. الان اونقدری سواد کافی از فلسک دارین که بتونید چنین پروژهای رو انجام بدین. پس برین خدا پشت و پناهتون!
روز بیستم: احراز هویت کاربران (دستی)
امروز میرسیم به یه بخش خیلی جذاب! اینکه چطوری سیستمی پیادهسازی کنیم که بشه ثبتنام کرد، لاگین و لاگاوت کرد و اینکه بفهمیم طرف اصلا کیه؟ ادمینه؟ یا یوزر معمولی؟ شاید فکر کنید این کار یه سیستم خیلی پیچیدهاس یا اصلا ایدهای نداشته باشین که این سیستم چطوری میخواد کار کنه؟ برای همین میخوایم این بخش رو به دو شکل بنویسیم. دستی و اتوماتیک. اول دستی رو کار میکنیم که پایه خیلی قوی پیدا بکنید نسبت به این مبحث.
اصولا لاگین یعنی کاربر بیاد یوزرنیم و رمز رو بزنه و رمز رو هش بکنیم و ببینیم با اون رمزی که توی دیتابیس هش شده یکی هستش؟ و اگر بود برای کاربر یه سیشن بسازیم و آیدی کاربر رو اونجا بذاریم (آیدی عددی منظورمه) بعدش جاهایی که نیاز هست کاربر لاگین کرده باشه، چک کنیم که آیا سیشنی برای کاربر هست که توش آیدی کاربر باشه؟ اگر هست آیدی رو برداریم و یه کوئری بزنیم و اطلاعات کاربر رو بگیریم. اگر نیست بگیم شرمنده برین لاگین کنید و بعد برگردین!
و اصولا لاگ اوت یعنی همون سیشن که ساخته شده رو بزنیم حذف کنیم! همچنین شما میتونید برای اون سیشن یه تاریخ تنظیم کنید که مثلا کاربر 2 ساعت لاگین باقی بمونه بعدش لاگ اوت بشه. مثلا توی دیجیکالا اون سیشن از بین نمیره مگر اینکه شما خودتون بزنید کش رو پاک کنید. اما مثلا توی بلاگفا مرورگر رو ببندید اون سیشن هم حذف میشه. دیگه بستگی به چیزی داره که میخواین بسازین.
خب برای پیاده سازی سیستم احراز هویت اول مدل کاربر رو میخوایم:
همچنین نیاز به یه فرم لاگین داریم توی login.htm:
نکته: اون st رو بعدا میبینیم که چیه!
نیاز به یه فرم ثبتنام هم داریم توی register.htm:
اول بریم ثبتنام رو بنویسیم چون تا وقتی کاربری ثبت نکرده باشیم، با رمز و یوزرنیم کی وارد بشیم آخه؟! اینجا باید یه چیزی بگم. اون رمزی که کاربر وارد میکنه رو نباید دقیقا همونو وارد کنیم توی دیتابیس! چون خیلی تابلوعه! چون خیلی امنیت میاد پایین. پس میایم اول یوزرنیم و پسورد رو میگیریم، پسورد رو هش میکنیم و سپس یه شی از مدل User میسازیم. برای هش کردن نیاز به یه کتابخانه داریم به اسم flask-bcrypt پس باید نصبش کنید:
اگر به مخازن pypi دسترسی ندارین، از اینجا میتونید یاد بگیرین چطوری میشه کتابخانههای پایتون رو بدون دسترسی مستقیم به pypi نصب کرد.
حالا ویوو مربوط به ثبتنام رو ببینید:
اگر مباحث مربوط به پایگاه داده و فرمها رو خوب یاد گرفته باشین اینجا لازم نیست من هیچ توضیحی بدم! فقط توی خط 7 اومدیم رمزی که کاربر زده رو هش کردیم… بدیهی هم هست که چیزایی مثل reuqest, redirect, url_for و… رو باید بالا ایمپورت کرده باشین.
خب این از ثبتنام. برای لاگین باید دوباره ورودیهای کاربر رو بگیریم بعدش اون کاربری که اون username داره رو پیدا بکنیم و بعد چک کنید هش شده رمز اون کاربر با هش شده رمز ورودی یکی هست؟ اگر باشه خب یعنی کاربر رمز رو درست زده پس باید لاگین بشه. لاگین یعنی چی؟ یعنی اینکه یه سیشن بسازیم و توش user.id رو قرار بدیم:
به کوئری که خط 7 زدم و شرطی که توی خط 9 نوشتم دقت کنید. البته اون .first که نوشتم اضافه کاریه چون یوزرنیم رو توی مدل unique تعریف کردیم.. نمیشه دو تا باشه. ولی در کل خواستم اینجا اینم بهتون نشون بدم چیزی به اسم first داریم…
حالا اگر کاربر وجود نداشته باشه یا رمز غلط باشه، پیج login.htm به کاربر نشون داده میشه منتها یه چیزی توی st ریخته میشه. یه جور status که بعدش توی تمپلیت دیدین اونو گرفتیم و گفتیم اگر چیزی بود نشون بده.
حالا کاربر لاگین کرده. میخواد بره توی profile اش. باید چیکار کنیم؟ باید توی ویوو پروفایل اول چک کنیم که سیشن user_id وجود داره؟ اگر نداشت کاربر ریدایرکت بشه به بخش لاگین، اگر وجود داشت آیدی رو میگیریم و اطلاعات یوزر رو پیدا میکنیم و میفرستیم به تمپلیت:
و توی تمپلیت به user دسترسی داریم:
حالا کاربر میخواد لاگ اوت بکنه. لاگ اوت هم که گفتم یعنی اون سیشن رو بزنیم پاک کنیم:
ما میتونیم توی صفحه اصلی، ببینیم کاربر لاگین کرده یا نه؟ اگر لاگین کرده، لینک لاگ اوت و پروفایل بهش نشون داده بشه. اگر لاگ اوت کرده بهش لینک لاگین و ثبت نام رو نشون بدیم:
و بعد توی تمپلیت:
شاید باورتون نشه ولی کل ماجرا همین بود! توی پروژه واقعی هم از این استفاده کنید درسته! کار با flask-login که روز بعدی از آموزش رایگان فلسک کار میکنیم باهاش هم بر همین پایهاس. حالا یه سری چیزای بیشتری هم داره که خواهیم دید…
حمایت از این مجموعه آموزشی 💖
این مجموعه آموزشی به رایگان در اختیار شما قرار داده شده ولی اگر دوست داشتین همیشه میتونید از من حمایت کنید. با خریدن یه قهوه برام! لینک حمایت مالی از آقای ربات (40 هزار تومان به بالا)
روز بیست و یکم: احراز هویت کاربران (با flask-login)
روز قبلی ما با اساس و پایه احراز هویت آشنا شدیم. حالا میخوایم با یه پکیج که کار احراز هویت رو راحتتر و حرفه ای تر میکنه آشنا بشیم، به اسم flask-login… البته اساس کار این پکیج باز هم همون سیشن هستش فقط حرفه ای تر هستش و میشه توش چیزای مختلفی رو مثل remind me و… رو تنظیم کرد. اول از همه باید نصبش کنید:
بعدش توی models.py ما باید یه مدل میکسین به اسم UserMixin ایمپورت کنیم و به مدل یوزر بگیم ازش ارث بری بکنه پس اینطوری میشه:
این به مدل ما یه سری قابلیت اضافه میکنه که آیا مثلا کاربر لاگین کرده؟ آیا ادمینه و…
حالا توی app.py مشابه روش قبلی ما باید همچنان از bcrypt و اینا استفاده بکنیم فقط بگم که از flask-login اینا رو باید ایمپورت کنید:
بعد از اینکه دیتابیس رو مشخص کردیم باید از لاگین منیجر یه شی بسازیم و ویوو مربوط به لاگین رو بهش معرفی کنیم:
حالا قبل از تمام ویووها باید یه ویوو رو بنویسیم که آیدی میگیره و یوزر رو میده! بهش میگن یوزر لودر:
خب… حالا بریم سراغ بخش های مختلف… بخش ثبت نام دقیقا همون قبلیه.. هیچ فرقی نداره.
توی بخش لاگین وقتی کاربر رمز و یوزرنیمش درست باشه به جای اینکه سیشن بسازیم از login استفاده میکنیم:
به خط 10 توجه کنید!
توی بخش پروفایل به جای اینکه چک کنیم سیشن user_id وجود داره یا نه، از دکوراتور login_required استفاده میکنیم:
چون ما بالاتر ویوو لاگین رو به لاگین منیجر معرفی کردیم، اینجا اگر کاربر لاگین نکرده باشه، هدایت میشه به اون صفحه. بعدش توی پروفایل اگر خواستیم به یوزر دسترسی داشته باشیم میتونیم از current_user استفاده کنیم:
و برای بخش لاگ اوت هم از logout استفاده میکنیم:
ما میتونیم توی صفحه اصلی، ببینیم کاربر لاگین کرده یا نه؟ اگر لاگین کرده، لینک لاگ اوت و پروفایل بهش نشون داده بشه. اگر لاگ اوت کرده بهش لینک لاگین و ثبت نام رو نشون بدیم:
یه چیز باحال هم اینه که توی بخش home نیازی نیست یوزر یا پارامتری یا فلگ ای ارسال کنیم. به جاش مثلا برای چک کردن اینکه کاربر لاگین کرده یا نه میشه نوشت:
اگر میبینید براتون زیادی ساده اس، به خاطر اینه که روز قبلی که احراز هویت رو با سیشن نوشتیم خیلی خوب درک کردین و اگر میبینید براتون زیادی پیچیده اس، به خاطر اینه که روز قبلی رو هنوز خوب درک نکردین. پس به خودتون مهلت بدین و مرور کنید…
حمایت از این مجموعه آموزشی 💖
این مجموعه آموزشی به رایگان در اختیار شما قرار داده شده ولی اگر دوست داشتین همیشه میتونید از من حمایت کنید. با خریدن یه قهوه برام! لینک حمایت مالی از آقای ربات (40 هزار تومان به بالا)
روز بیست و دوم: آپدیت پروژه TodoList
خب… تا اینجا شما چیزهای زیادی از فلسک یاد گرفتین! حالا بیاین پروژه تودولیست که روز نوزدهم ساختین ارتقا بدین و بخش احراز هویت رو بهش اضافه کنید. یعنی تسک ها به مدل یوزر وابسته باشن. هر تسک مال یه یوزر باشه. یوزر وقتی لاگین کرد بتونه صفحه اول رو ببینه (صفحه اول از دکوراتور @login_required استفاده کنید) و کاربر بتونه تسک های خودش رو توی داشبوردش مدیریت بکنه.
یا بعدا میتونید همین پروژه رو تبدیل کنید به یه مینی توییتر، یا یه سیستم بلاگ شخصی! اگر بهش فکر کنید تقریبا هر سه تای این پروژه ها به یه شکل کار میکنن!
روز بیست و سوم: مدیریت خطا در فلسک
به اینجای قصه که رسیدین شما رو دعوت میکنم به این لینک تا در مورد خطاهای رایج و کد اونها توی وب آشنا بشین. یکیشو احتمالا بلد باشین: 404… کد 404 به این معنیه که کاربر میخواسته بره صفحه ای که وجود نداره! یا مثلا خطای 500 به این معنیه که برای سرور یه مشکلی پیش اومده.. حتما برین اینا رو بخونید.
خب حالا مثلا ما میخوایم برای خطای 404 یه صفحه طراحی بکنیم و بگیم کاربر میخواست وارد صفحهای بشه که وجود نداشت یا به عبارتی وقتی خطای 404 میخواست رخ بده، کاربر رو هدایت بکن به یه صفحه خاص و بهش بگو این خطا رخ داده. برای این کار یه دکوراتوری توی فلسک وجود داره به اسم @app.errorhandler که استفاده ازش به این شکله که ما این دکوراتور رو مینویسیم و یه تابع میدیم بهش تا در زمان بروز اون خطا، اون تابع فراخوانی بشه. مثلا برای خطای 404:
داخل errorhandler باید کد خطا رو بنویسید. اون 404 که داخل تابع return شده تاثیری توی کار نداره فقط توی محیط ترمینال، اون خطا رو مینویسه. یعنی برای لاگ گرفتن استفاده میشه. که کاربر میخواسته بره فلان جا، ولی این صفحه بهش نشون داده شده. یعنی کاربری که این صفحه رو دیده به خاطر بروز خطای 404 بوده!
یادتون نره که تابعی که برای این دکوراتور مینویسیم یه e (یه پارامتر دلخواه) میگیره.
حالا شما باید توی templates یه صفحه 404.html بسازین و طراحی کنید که به کاربر نشون داده بشه. خطای 500 رو هم اگر بخوایم مدیریت کنیم:
احتمالا لازم نباشه بگم ولی اسم تابع دلخواه هستش. من اینطوری نوشتم که خوانا باشه وگرنه اسم تابع رو “گیتار” بنویسید هم بازم موقع خطای 500 اجرا میشه!
حمایت از این مجموعه آموزشی 💖
این مجموعه آموزشی به رایگان در اختیار شما قرار داده شده ولی اگر دوست داشتین همیشه میتونید از من حمایت کنید. با خریدن یه قهوه برام! لینک حمایت مالی از آقای ربات (40 هزار تومان به بالا)