אומרים שאין חכם כבעל נסיון, והכי טוב ללמוד זה ״דרך הרגליים״ (וידוע שבעגה הצבאית אומרים קד״ר שזה קליטה-דרך-הרגליים) וזו אכן היתה החויה שלי כשניגשתי לפתח אפליקציה עם המערכת של Django. פשוט התחלתי לעשות ולמדתי כל כך הרבה תוך כדי תנועה.
הערה חשובה:
כשאני אומר ׳אפליקציה׳ אני מתכוון לאפליקציית ווב, כזו שרצה על הדפדפן במחשב שלכם או בטלפון. לצורך העניין גם הבלוג הזה שאתם קוראים בו כרגע הוא אפליקציה, וגם הרשת החברתית האהובה עליכם (בגירסת הדפדפן). אפליקציית ווב (web) היא לא פחות ׳שווה׳ מאפליקציה שרצה על הטלפון ישירות. אבל קל יותר לפתח אותה ולהגיש אותה למשתמשים ולכן בזה אנו עוסקים כרגע. ועכשיו תמשיכו לקרוא:
אולי אתם אומרים לעצמכם ״כן אביץ, אבל אתה יודע תיכנות, יש לך רקע טכני טוב, וזה פחות חכמה״ אז הנה קחו דוגמא מריילי בראון. ריילי הוא בלוגר שסוקר לא מעט חדשות בינה מלאכותית. כשיצא המודל החדש של קלוד סונט 3.5 – ריילי קיבל טעימה מהיופי של עולם הקוד כאשר הוא ביקש מהמודל שייצור לו כל מיני דברים והם פשוט הופיעו למולו על גבי ממשק ה״תוצרים״ (Artifacts).
ריילי לא הסתפק בזה ושאל את עצמו: מה עוד אוכל לפתח עם קלוד? והוא פשוט שאל את קלוד האם הוא יכול לפתח אפליקצייה מלאה שתהיה באינטרנט, עם דומיין משלו, ותעבוד ממש כמו כל אפליקציה אמיתית… הוא שאל – וקלוד ענה. הוא ביקש מקלוד שידריך אותו באיזה שירות להשתמש ואיך להתקין מה שצריך – וקלוד ענה. הוא ביקש מקלוד שיכתוב לו קוד – וקלוד כתב. הוא העתיק את הקוד וכשהיו טעויות הוא ביקש מקלוד שיתקן – וקלוד תיקן. ריילי לא כתב שום קוד בחייו עד לאותו היום… אבל מאותו רגע הוא התאהב ביכולת שלו להגשים מה שעולה לו בדמיון – בצורה אינטואיטיבית כל כך. אז הנה: לחצו כאן לשיתוף המלא של ריילי בערוץ שלו.
ונחזור ל-Django.
ללמוד דרך עשייה, דרך התנסות, דרך אתגרים. זה מדהים בעיניי… אז הנה כמה רעיונות בסיסיים שלמדתי על פיתוח צד שרת עם Django.
צד שרת – למי שטרם הכיר את הביטוי – הכוונה לקוד שנשאר על השרת המרוחק של האפליקציה ולא נשלח אל המחשב של המשתמש. לעומת קוד צד לקוח, שנשלח כמות שהוא אל המשתמש ומפוענח באמצעות הדפדפן על גבי המחשב של המשתמש. אם למשל תכניסו איזושהי סיסמא פרטית שלכם לתוך הקוד צד לקוח (למשל HTML או Javascript) זה אוי ואבוי – כי כל מי שיגלוש באתר שלכם מקבל את הקוד הזה אליו ויכול לראות את הסיסמא שלכם. ביג נו נו. אבל צד שרת נשאר על השרת ואף אחד מלבד מי שיש לו הרשאה מיוחדת, כמוכם, לא יכול לגשת לשם.
עכשיו בדרך כלל עובדים על הקוד צד שרת והקוד צד לקוח בנפרד, מכיון שאלו באמת שתי מערכות שפועלות בנפרד. כל מערכת כזו רצה ומפוענחת על מחשב אחר, כמו שאמרנו. במקרה שלנו: הקוד צד שרת הוא קוד פייתון (עם ספרייה שנקראת framework בשם Django) – על גבי השרת המרוחק יש תוכנת פייתון שמפענחת את הקוד ומבצעת את מה שצריך…
וכעת למושגים:
אז פרוייקט ב-Django משלב כמה קבצים מרכזיים. חשוב שתכירו אותם, תדעו פחות או יותר על מה הם אחראיים, ותבינו מתוך כך למה צריך לשים לב כשמפתחים אפליקציה באמצעות קלוד (או כל מודל קוד אחר) שכותב לכם את הקוד של Django.
קובץ settings.py

זה סוג של בסיס האם של הפרוייקט. שם יש הגדרות חיוניות שבלעדיהן שום דבר לא יזוז. בתוך הפרוייקט צריך להיות לכם לפחות ״אפליקציה״ אחת, שיש לה תיקייה יעודית פנימית יותר לתיקיית הבסיס שלכם, והיא מוגדרת בקובץ הזה. גם הגדרות של דטה-בייס, וגם משהו מוזר שנקרא Middleware שכמו שזה נשמע זה משהו שעומד בין לבין, אלו כל מיני תהליכים שקורים כשפונים לשרת לפני שהאפליקציה שלכם נכנסת לפעולה. כנראה…
קובץ models.py

זה הלב, המהות. הקובץ שכדאי לכם לתת לו הרבה יחס. אם Settings זה כל הבירוקרטיה הזו שאי אפשר בלעדיה – אז ה Models זה הכיף האמיתי. כאן למעשה מוגדר מבנה הנתונים שלכם, וכל אפליקציה במיוחד של Django יושבת בראש ובראשונה על מבנה נתונים מסויים שמותאם במיוחד לאפליקציה. לפני שקורים דברים, לפני שיש ממשקים גרפיים מרהיבים, אפילו לפני שנכנסים דברים לדטה-בייס (שזה בעצם הזכרון לטווח ארוך שלכם) – יש מבנה נתונים. או בשפה של עולם הפיתוח: יש מודל. ושימו לב לא להתבלבל עם מושגים אחרים שקשורים למידה מודל (כמו מודל בינה מלאכותית לדוגמא…)
ההגדרה של מבנה הנתונים שלכם (המודל) זה מה שיתקבע בתוך הדטה בייס, ככה הוא יצפה לקבל את המידע, לפי המבנה שתגדירו. כל נתון חדש יהיה חייב למלא את השדות שתגדירו כאן. למשל: בתמונה למעלה יש מחלקה (סוג של נתון, לצורך העניין) שנקראת Test שזה מבחן. ומוגדר שם שלכל מבחן חייב להיות name (כלומר שם), description (תיאור) ועוד שני שדות של תאריכים של זמן יצירת המבחן וזמן העדכון שלו… כל נתון כזה חייב לשמור על מבנה מסויים שמוגדר, למשל שם אסור לו לעבור את מאה התווים (שזה בסדר אבל עדיין הכל מוגדר). בדרך כלל לא תצטרכו לדאוג לדברים האלה, הכל קורה מאחורי הקלעים באופן מסודר – אבל חשוב שתבינו איך זה עובד.
והדבר שמאוד חשוב לדעת: כל שינוי של מבנה הנתונים, כלומר של הגדרת המחלקות השונות, בין אם זה להוסיף פרטים או אפילו לשנות את מגבלת התוים של השם (כן, גם זה נחשב שינוי) מצריך פעולה שנקראת ״מיגרציה״ (מזכיר מרגרינה, תזכרו). שזה אומר שמבצעים התאמה של הדטה בייס למבנה החדש. כי דטה-בייס זה עולם קשוח שעובד בטבלאות שבנויות לקבל סוג נתונים מסויים, ואם אחרי שכבר הכנסתם אליה כל מיני נתונים פתאום אתם משנים משהו בהגדרות שלה – זה סמטוחה עם כל הנתונים שכבר קיימים שם, אז לכן עושים מיגרציה. אבל שוב – אתם לא באמת צריכים לדאוג. הכל קורה לבד. אבל אתם צריכים להפעיל פקודה שנקראת createmigrations שיוצרת תהליך של מיגרציה ואח״כ עוד פקודה migrate. זה פשוט עושה סדר בשבילכם עם המצב החדש של הנתונים והדטה בייס. פשוט שתעריכו – נעשית פה עבודה מורכבת מאחורי הקלעים… וגם אם פתאום משהו קורה לא כמצופה ויש תקלות אז שתכירו מה יכול להשתבש.
קובץ serializers.py

זה קובץ די טכני שאין ממש מה לחשוב עליו, אלא לתת לקלוד לכתוב אותו. מה שכן חשוב כמו תמיד – זה לשים לב שקלוד מכיר מספיק את ההקשר, וכמובן מכיר את הקובץ models.py בזמן שהוא כותב את הקובץ הזה או עורך אותו. באופן כללי, עם כל הצעה שקלוד נותן לקובץ הזה (וגם לקבצים אחרים) אני ממליץ להגיש לו את מצב הקובץ הנוכחי ואז שהוא יתן את ההצעה (ולא שיציע מה לכתוב בקובץ לפני שהוא יודע מה יש בו כרגע כי אז הוא יכול להעלים לכם חלקים שלמים שהוא לא היה מודע לקיומם) ובאותה הגשה לצרף גם את ה models.py כי שניהם ממש צמד שהולך יחד, שני הקבצים האלה, והם צריכים לעבוד בתיאום מלא ומדוייק. אם יש פרטים שלא מנוסחים באופן זהה בשניהם אז יהיו בעיות.
אז מה עושה serializers.py הוא אחראי להכניס את הנתונים לתוך הדטה בייס, מכיון שהאופן שבו הנתונים מיוצגים באפליקציה זה לא אחד לאחד האופן שבו הם שמורים בדטה בייס. אז על המעבר הזה אחראי ה-serializer.
קובץ views.py

טוב, זה כנראה הקובץ המגניב שבו ממש דברים קורים. כלומר כל דבר שאשכרה קורה באפליקציה שלנו – מוגדר בקובץ הזה. למעשה views אמור להתייחס לתצוגה, לחזית של האפליקציה שלכם. אבל הרבה פעמים מה שקורה ב-views לא בהכרח מוצג החוצה באופן ויזואלי אבל הוא כן פונה כלפי חוץ, כלומר כלפי הממשק או המשתמש שנמצא אי שם.
כאשר מישהו פונה לאפליקציה, הוא מנותב ל-views ושם הוא מקבל טיפול. אם צריך ליצור מודל נתונים אז ה-views אחראי על זה, הוא יוצר נתון על פי המודל שהוגדר ב-models ואז מבקש לשמור אותו למשל והשמירה עוברת דרך serializers לפני שהיא נכנסת לדטה בייס. עד כאן מובן?
כמו שניתן לראות בדוגמא פה בתמונה, מחלקה בשם BudgetViewSet
יש לה פונקציה שמגיבה לקריאת get כלומר בקשה שמגיעה מבחוץ שרוצה ׳לקבל׳ מידע, לעומת הפעולה השניה שמגיבה לבקשה מסוג post והיא מעוניינת בשליחת מידע חדש ושמירה שלו בדטה-בייס, ובאמת budget.save()
זה קריצה ל-serializer לשמור את המידע החדש בדטה בייס.
קובץ אחרון חביב להיום:
קובץ urls.py

מכירים את זה שאתם כותבים בשורת כתובת כל מיני ביטויים שאמורים להעביר מידע לשרת המרוחק, למשל ביוטיוב https://www.youtube.com/watch?v=QSabADqrz9g אז יש לנו את הדומיין העיקרי youtube.com אבל אחריו יש /watch שזה נתיב פנימי ואחריו גם יש עוד פרמטר שעובר v=QSabADqrz9g אז הקובץ urls.py בעצם קולט את כל הפניות האלה ולפי הנתיב הוא מפנה את הבקשה לאיזור הרצוי. במקרה שלנו יש רישום של כל הביטויים של המחלקות השונות, למשל אם הדומיין שלנו הוא example.com (מה שלא סביר, אבל לצורך הדוגמא) אז קריאה example.com/tests יפנה אותנו ל-view שלו ואז לפי אופי הבקשה אם זה למשל get או post יתבצעו דברים שונים שמוגדרים ב-view.
לסיכום כרגע…
אפליקציה ב-Django בנויה כמו גלדים של בצל, אחד בתוך השני. הלב הוא models תחתיו יש את ה-Serializers שמתקשר עם הדטה-בייס, מעליו יש את ה-views ומעליו ה-urls. כל הקבצים חייבים להיות מסונכרנים ביניהם וזה מאוד חשוב ולכן כל נושא אורך הקונטקסט של קלוד הוא קריטי כאן כי חשוב שהוא יכתוב את הקבצים מתוך היכרות עם המרחב של שאר הקבצים.
אחרי ששסיימתם להכין את הקבצים האלה והם באמת משקפים את כל סוגי הפעולות שחשוב לכם שהאפליקציה שלכם תדע לבצע ולנהל – אז תוכלו לבנות טסטים שבודקים שהאפליקציה באמת מתנהגת כמצופה במישור הזה. ואם הכל פיקס אפשר להמשיך לבניית הממשק, קוד צד לקוח.
עד כאן להפעם, מקווה שנתרמתם. תכתבו לי בתגובות 🙂
כתיבת תגובה