המחבר בחר ב־קרן הקוד הפתוח והחופשי לקבלת תרומה כחלק מתוכנית כתוב בשביל תרומות.
הקדמה
Flask הוא פריימוורק קל משקל עבור פייתון המספק כלים ותכונות שימושיים ליצירת אפליקציות אינטרנט בשפת פייתון. SQLAlchemy הוא ערכת כלים ל־SQL המספקת גישה יעילה וביצועית למסדי נתונים רציונליים. היא מספקת דרכים לפעול עם מנועי מסדי נתונים שונים כמו SQLite, MySQL, ו־PostgreSQL. היא מעניקה לך גישה לתכונות ה־SQL של מסד הנתונים. היא מעניקה גם לך Mapper עצם יחסי (ORM), אשר מאפשר לך לבצע שאילתות ולטפל בנתונים באמצעות אובייקטים ושיטות בפייתון. Flask-SQLAlchemy היא תוספת ל־Flask המקלה על שימוש ב־SQLAlchemy עם Flask, ומספקת לך כלים ושיטות לפעול עם מסד הנתונים שלך ביישומי Flask שלך דרך SQLAlchemy.
A many-to-many database relationship is a relationship between two database tables where a record in each table can reference several records in the other table. For example, in a blog, a table for posts can have a many-to-many relationship with a table for storing authors. Each post can have many authors, and each author can write many posts. Therefore, there is a many-to-many relationship between posts and authors. For another example, in a social media application, each post may have many hashtags, and each hashtag may have many posts.
במדריך זה, תשנה אפליקציה שנבנתה בעזרת Flask ו־Flask-SQLAlchemy על ידי הוספת יחס רבים לרבים אליה. תהייה לך יחס בין פוסטים ותגיות, כאשר כל פוסט בבלוג יכול להכיל מספר תגיות, וכל תגית יכולה להכיל מספר פוסטים שתוייגו בה.
איך להשתמש ביחסי מסד נתונים One-to-Many עם Flask-SQLAlchemy הוא סדרת המשך של המדריך שבו אתה בונה מסד נתונים מרובה טבלאות עם יחס one-to-many בין פוסטים ותגובות ביישום לבלוגים.
עד סופו של המדריך, היישום שלך יכלול תכונה חדשה להוספת תגיות לפוסטים. פוסטים יכולים לקבל תגים מרובים, וכל עמוד תג יציג את כל הפוסטים שקיבלו את התג הזה.
דרישות מוקדמות
-
סביבת פיתוח Python 3 מקומית. עקוב אחר המדריך להתקנת והגדרת סביבת פיתוח עבור Python 3 בסדרת כיצד להתקין ולהגדיר סביבת פיתוח מקומית עבור Python 3. במהלך המדריך, נקרא לתיקיית הפרוייקט שלנו
flask_app
. -
הבנת מושגים בסיסיים של Flask, כמו נתיבים, פונקציות צפייה, ותבניות. אם אינך מכיר את Flask, ראה כיצד ליצור את היישום הראשון שלך באינטרנט באמצעות Flask ו-Python ו-כיצד להשתמש בתבניות ביישום של Flask.
-
הבנת מושגים בסיסיים של HTML. ניתן לעיין בסדרת השיעורים שלנו כיצד לבנות אתר אינטרנט בעזרת HTML לידע בסיסי מראש.
-
(אופציונלי) בשלב 1, תעתיק את אפליקציית הבלוגים שתעבוד עליה במדריך זה. עם זאת, באפשרותך לעבוד דרך מדריך כיצד להשתמש ביחסי מסד נתונים אחד לרבים עם Flask-SQLAlchemy. ניתן לגשת לקוד הסופי מהעמוד הזה.
שלב 1 — הגדרת אפליקציית האינטרנט
בשלב זה, תכינו את אפליקציית הבלוגים כך שתהיה מוכנה לשינויים. תבדקו גם את מודלי מסד הנתונים של Flask-SQLAlchemy ואת הנתיבים של Flask כדי להבין את מבנה האפליקציה. אם עקבתם אחר המדריך במקטע הדרישות המוקדמות ויש לכם את הקוד ואת הסביבה הווירטואלית על המחשב המקומי שלכם, תוכלו לדלג על שלב זה.
כדי להדגים הוספת יחס רבים-אל-רבים ליישום אינטרנט ב־Flask עם Flask-SQLAlchemy, תשתמש בקוד היישום מהמדריך הקודם, שהוא מערכת בלוגים עם יכולת להוסיף ולהציג פוסטים, להגיב על פוסטים, ולקרוא ולמחוק הערות קיימות.
שכפל את המאגר ושנה את שמו מ־flask-slqa-bloggy
ל־flask_app
באמצעות הפקודה הבאה:
נווט לתיקיית flask_app
:
לאחר מכן צור סביבת עבודה וירטואלית חדשה:
הפעל את הסביבת העבודה:
התקן את Flask וְ-Flask-SQLAlchemy:
לאחר מכן, הגדר את משתני הסביבה הבאים:
FLASK_APP
מציין את היישום שאתה פותח כעת, שהוא app.py
במקרה זה. FLASK_ENV
מציין את מצב הפעולה. תגדיר אותו ל־development
למצב פיתוח; זה יאפשר לך לאתר באגים ביישום. זכור לא להשתמש במצב זה בסביבת הפרודקשן.
לאחר מכן, פתח את שאל Flask כדי ליצור את טבלאות המסד נתונים:
לאחר מכן ייבא את עצם מסד הנתונים Flask-SQLAlchemy, את מודל ה־Post
, ואת מודל ה־Comment
, וצור את טבלאות מסד הנתונים באמצעות פונקציית ה־db.create_all()
:
לאחר מכן הוסף נתונים למסד הנתונים באמצעות התוכנית init_db.py
:
פעולה זו מוסיפה שלושה פוסטים וארבעה הערות למסד הנתונים.
הפעל את שרת הפיתוח:
אם תעבור לדפדפן שלך, תראה את היישום פועל בכתובת ה-URL הבאה:
http://127.0.0.1:5000/
תראו עמוד דומה לזה:
אם תקבלו שגיאה, ודאו שעקבתם אחר השלבים לעיל בצורה תקינה.
כדי לעצור את שרת הפיתוח, השתמשו ב־CTRL + C
.
לאחר מכן, תעברו על דפי המודלים של מסד הנתונים של Flask-SQLAlchemy כדי להבין את היחסים הנוכחיים בין הטבלאות. אם אתם מכירים את תוכן קובץ app.py
, תוכלו לדלג לשלב הבא.
פתחו את קובץ app.py
:
תוכן הקובץ הוא כדלקמן:
כאן יש לכם שני מודלי מסד נתונים המייצגים שני טבלאות:
-
Post
: שיש לו עמודת ID, כותרת, תוכן, ויחס One-to-Many עם טבלת התגובות. -
Comment
: שיש לו עמודת ID, עמודה עבור התוכן, ועמודהpost_id
להתייחסות לפוסט שבו נמצאת התגובה.
מתחת למודלים יש לכם את הנתיבים הבאים:
/
: עמוד האינדקס, שמציג את כל הפוסטים במסד הנתונים./<int:post_id>/
: עמוד הפוסט היחידי. לדוגמה, הקישורhttp://127.0.0.1:5000/2/
מציג את פרטי הפוסט השני במסד הנתונים ואת התגובות שלו./comments/
: עמוד שמציג את כל התגובות במסד הנתונים ומקשר לפוסט שבו פורסמה כל תגובה./comments/<int:comment_id>/delete
: נתיב שמוחק תגובה דרך לחצן מחק תגובה.
סגור את קובץ app.py
.
בשלב הבא, תשתמש ביחס רבים-לרבים כדי ליצור קישור בין שני טבלאות.
שלב 2 — הגדרת מודלי מסד נתונים עבור יחס רבים-לרבים
בשלב זה, תוסיף מודל מסד נתונים שיצג את טבלת התגיות. תקשור אותו עם טבלת הפוסטים הקיימת באמצעות טבלת קשר, שהיא טבלה שמחברת את שתי הטבלאות שלך ביחס רבים-לרבים. יחס רבים-לרבים מקשר שתי טבלאות שבהן כל פריט בטבלה יש פריטים רבים הקשורים בטבלה השנייה. בטבלת הקשר, כל פוסט יפנה לתגיות שלו וכל תג יפנה לפוסטים המתוייגים עם התג. תכניס גם מספר פוסטים ותגיות למסד הנתונים שלך, תדפיס פוסטים עם התגיות שלהם, ותדפיס תגיות והפוסטים הקשורים אליהם.
נניח שיש לך טבלה פשוטה עבור פוסטי בלוג כך:
Posts
+----+-----------------------------------+
| id | content |
+----+-----------------------------------+
| 1 | A post on life and death |
| 2 | A post on joy |
+----+-----------------------------------+
וטבלה עבור תגים כך:
Tags
+----+-------+
| id | name |
+----+-------+
| 1 | life |
| 2 | death |
| 3 | joy |
+----+-------+
תנסה לסמן פוסט על חיים ומוות
עם התגיות חיים
ו־מוות
. ניתן לעשות זאת על ידי הוספת שורה חדשה בטבלת הפוסטים כך:
Posts
+----+-----------------------------------+------+
| id | content | tags |
+----+-----------------------------------+------+
| 1 | A post on life and death | 1, 2 |
| 2 | A post on joy | |
+----+------------------------------------------+
שיטה זו אינה עובדת, מכיוון שכל עמודה צריכה לכלול ערך יחיד בלבד. כאשר ישנם ערכים מרובים, פעולות בסיסיות כגון הוספה ועדכון נתונים מסתבכות ואיטיות. במקום זאת, יש ליצור טבלה שלישית שמפנה את המפתחות הראשיים של הטבלאות הקשורות – לטבלה זו נקראת לעיתים טבלת עמודות חיבור או טבלת הצמיחה, והיא מאחסנת מזהים של כל פריט מכל טבלה.
להלן דוגמה לטבלת הצמיחה שמקשרת בין פוסטים ותגיות:
post_tag
+----+---------+-------------+
| id | post_id | tag_id |
+----+---------+-------------+
| 1 | 1 | 1 |
| 2 | 1 | 2 |
+----+---------+-------------+
בשורה הראשונה, הפוסט עם המזהה 1
(שזהו, פוסט על חיים ומוות
) מתייחס לתג עם המזהה 1
(חיים
). בשורה השנייה, אותו פוסט גם מתייחס לתג עם המזהה 2
(מוות
). זה אומר שהפוסט מסומן גם בתגיות חיים
ו־מוות
. באופן דומה, ניתן לסמן כל פוסט עם מספר תגיות.
עכשיו, תשנה את קובץ app.py
כך שתוסיף מודל מסד נתונים חדש שמייצג את הטבלה שבה תשמור תגיות. תוסיף גם טבלת post_tag
המקשרת בין פוסטים לתגיות.
לפני כל דבר, פתח את app.py
כדי להקים קשר בין פוסטים ותגיות:
הוסף טבלת post_tag
ומודל Tag
מתחת לאובייקט db
ומעל המודל Post
, ואז הוסף יחס tags
pseudo-column למודל Post
כך שתוכל לגשת לתגיות של הפוסט דרך post.tags
ולגשת לפוסטים של תג דרך tag.posts
:
שמור וסגור את הקובץ.
כאן אתה משתמש בפונקציית db.Table()
כדי ליצור טבלה עם שני עמודות. עבור טבלאות של התחברות, פרקטיקה הטובה היא להשתמש בטבלה במקום במודל במסד נתונים.
טבלת post_tag
מכילה שתי עמודות המייצגות שני מפתחות זרים, שהם מפתחות המשמשים להתייחסות לעמודות מפתח ראשית בטבלה אחרת:
post_id
: מפתח זר של מספר שלם המייצג את זיהוי הפוסט ומתייחס לעמודת הזיהוי בטבלתpost
.tag_id
: מפתח זר של מספר שלם המייצג את זיהוי התג ומתייחס לעמודת הזיהוי בטבלתtag
.
המפתחות הללו מקימים את היחסים בין הטבלאות.
מתחת לטבלת post_tag
, אתה יוצר מודל Tag
, המייצג את הטבלה שבה תאחסן את התגיות שלך. טבלת התגיות מכילה שתי עמודות:
id
: זיהוי התג.name
: שם התג.
אתה משתמש בשם התג במתודת __repr__()
המיוחדת כדי להעניק לכל אובייקט תג מיוצג מחרוזת ברורה למטרות איתור שגיאות.
אתה מוסיף משתנה קבוע tags
למודל Post
. אתה משתמש בשיטת db.relationship()
, ומעביר לה את שם מודל התגים (Tag
במקרה זה).
אתה מעביר את טבלת הקישורים post_tag
לפרמטר secondary
כדי להגדיר יחס רבים-לרבים בין פוסטים ותגי פוסטים.
אתה משתמש בפרמטר backref
כדי להוסיף הפניה אחורית שתתנהג כמו עמודה למודל Tag
. בכך, תוכל לגשת לפוסטים של התג דרך tag.posts
ולתגי הפוסט דרך post.tags
. תראה דוגמה מדגימה לכך מאוחר יותר.
לאחר מכן, ערוך את קובץ התכנית פייתון init_db.py
כדי לשנות את מסד הנתונים ולהוסיף את טבלת הקישורים post_tag
ואת טבלת התגים המבוססת על מודל Tag
:
ערוך את הקובץ כדלקמן:
שמור וסגור את הקובץ.
כאן, אתה מייבא את המודל Tag
. אתה מוחק הכל מהמסד נתונים באמצעות פונקציית db.drop_all()
כדי להוסיף את הטאגים ואת הטבלה post_tag
בבטחה וכדי למנוע כל בעיות נפוצות הקשורות להוספת טבלאות חדשות למסד נתונים. לאחר מכן אתה יוצר את כל הטבלאות מחדש באמצעות הפונקציה db.create_all()
.
לאחר הקוד מהמדריך הקודם המכריז על הפוסטים והתגובות, אתה משתמש במודל Tag
כדי ליצור ארבעה תגיות.
אז אתה מוסיף תגיות לפוסטים באמצעות המאפיין tags
שנוסף דרך השורה tags = db.relationship('Tag', secondary=post_tag, backref='posts')
בקובץ app.py
. אתה משייך תגיות לפוסטים באמצעות שיטת append()
דומה לרשימות בפייתון.
בשלב הבא, אתה מוסיף את התגיות שיצרת למסד הנתונים באמצעות הפונקציה db.session.add_all()
.
הערה:
הפונקציה db.create_all()
לא תיצור מחדש או תעדכן טבלה אם היא כבר קיימת. לדוגמה, אם אתה משנה את המודל שלך על ידי הוספת עמודה חדשה ומריץ את הפונקציה db.create_all()
, השינוי שאתה עושה במודל לא ייושם על הטבלה אם הטבלה כבר קיימת במסד הנתונים. הפתרון הוא למחוק את כל טבלאות המסד הקיימות באמצעות הפונקציה db.drop_all()
ולאחר מכן ליצור אותן מחדש עם הפונקציה db.create_all()
, כפי שמודגם בקובץ init_db.py
.
התהליך הזה יחוליף את השינויים שתעשה לדפוסים שלך, אך ימחק גם את כל הנתונים הקיימים במסד הנתונים. כדי לעדכן את מסד הנתונים ולשמור על הנתונים הקיימים, יהיה עליך להשתמש בהגדרת המסכם, שמאפשרת לך לשנות את הטבלאות שלך ולשמור על הנתונים. באפשרותך להשתמש בהרחבה Flask-Migrate
כדי לבצע הגדרות מסכמת SQLAlchemy דרך ממשק השורת פקודה של Flask.
הרץ את התוכנית init_db.py
כדי ליישם שינויים במסד הנתונים:
התוכנית צריכה להריץ בהצלחה בלי פלט. אם אתה רואה שגיאה, ודא כי ביצעת את השינויים בקובץ init_db.py
בצורה תקינה.
כדי לצפות בפוסטים ובתגיות הקיימים כעת במסד הנתונים, פתח את מסך ה Flask:
הרץ את קוד הפייתון הבא שמעבור על פוסטים ותגיות:
כאן, אתה מייבא את הדגם Post
מתוך app.py
. אתה שואל את טבלת הפוסטים ומשיג את כל הפוסטים במסד הנתונים. אתה עובר על כל הפוסטים ומדפיס את כותרת הפוסט ואת רשימת התגיות המשויות עם כל פוסט.
תקבל פלט דומה לפלט הבא:
Output
Post The First
[<Tag "animals">, <Tag "writing">]
---
Post The Third
[<Tag "cooking">, <Tag "tech">, <Tag "writing">]
---
Post The Second
[]
---
אתה יכול לגשת לשמות התגיות באמצעות tag.name
כפי שמודגש בדוגמה הבאה, שאתה יכול להריץ בעזרת מסך ה Flask:
כאן, לצד הדפסת כותרת הפוסט, אתה עובר על כל התגיות של כל פוסט ומדפיס את שם התגית.
תקבל פלט דומה לפלט הבא:
OutputTITLE: Post The First
-
TAGS:
> animals
> writing
------------------------------
TITLE: Post The Third
-
TAGS:
> cooking
> tech
> writing
------------------------------
TITLE: Post The Second
-
TAGS:
------------------------------
כפי שאתה יכול לראות, התגיות שהוספת לפוסטים בתוכנית init_db.py
מקושרות כראוי לפוסטים שנתייגו בהן.
כדי לראות הדגמה של איך לגשת לפוסטים שתווייגו עם תג מסוים דרך tag.posts
, הרץ את הקוד הבא בתוך מסך הפלאסק:
אתה מייבא את מודל התג (Tag
). אז אתה משתמש בשיטת filter_by()
על התכונה query
ומעביר לה פרמטר name
כדי לקבל את התג writing
לפי שמו, ואתה מקבל את התוצאה הראשונה באמצעות שיטת first()
. אתה שומר את אובייקט התג במשתנה בשם writing_tag
. למידע נוסף על השיטה filter_by
, ראה שלב 4 של איך להשתמש ב-Flask-SQLAlchemy לקריאה עם מסדי נתונים ביישום Flask.
אתה עובר דרך הפוסטים שתווייגו עם התג writing
, שאליה אתה גושר דרך writing_tag.posts
. אתה מדפיס את כותרת הפוסט, התוכן, ורשימת שמות התגים שאתה בונה באמצעות רשימת קימפרהנשיין המבוססת על התגיות של הפוסט, אליהם אתה גושר דרך post.tags
.
תקבל פלט דומה לזה:
OutputPost The Third
------
Content for the third post
-
['cooking', 'tech', 'writing']
--------------------
Post The First
------
Content for the first post
-
['animals', 'writing']
--------------------
כאן אתה רואה את שני הפוסטים שתווייגו עם התג writing
, ושמות התגים מוצגים ברשימת פייתון.
כעת אתה יכול לגשת לפוסטים ולתגים שלהם ולגשת לפוסטים של תג מסוים.
אתה הוספת מודל בסיס נתונים שמייצג את טבלת התגיות. קשרת בין פוסטים ובין תגיות באמצעות טבלת איגוד, והכנסת כמה תגיות לבסיס הנתונים והקשת פוסטים אליהם. גישת פוסטים ותגיותיהם ופוסטי התג האישי. בשלב הבא, תשתמש ב-Flask shell כדי להוסיף פוסטים חדשים ותגיות חדשות ולקשר ביניהם, ותלמד איך להסיר תגיות מפוסט.
שלב 3 — ניהול נתונים ביחס רב לרב
בשלב זה, תשתמש ב-Flask shell כדי להוסיף פוסטים חדשים לבסיס הנתונים, להוסיף תגיות ולקשר בין פוסטים ותגיות. תגיש פוסטים עם תגיותיהם, ותראה כיצד לנתח פריט מפריט אחר ביחסי רב לרב.
ראשית, בעזרת סביבת התכנות שלך מופעלת, פתח את ה-Flask shell אם עדיין לא עשית זאת:
בשלב הבא, הוסף מספר פוסטים ותגיות:
from app import db, Post, Tag
life_death_post = Post(title='A post on life and death', content='life and death')
joy_post = Post(title='A post on joy', content='joy')
life_tag = Tag(name='life')
death_tag = Tag(name='death')
joy_tag = Tag(name='joy')
life_death_post.tags.append(life_tag)
life_death_post.tags.append(death_tag)
joy_post.tags.append(joy_tag)
db.session.add_all([life_death_post, joy_post, life_tag, death_tag, joy_tag])
db.session.commit()
זה יוצר שני פוסטים ושלוש תגיות. אתה מקשר פוסטים עם התגיות הקשורות אליהם, ואתה משתמש בשיטת add_all()
כדי להוסיף את הפריטים שנוצרו לאסימון בסיס הנתונים. אז אתה מכין את השינויים ומחייב אותם לבסיס הנתונים באמצעות השיטה commit()
.
בשלב הבא, השתמש ב-Flask shell כדי לקבל את כל הפוסטים ותגיותיהם כמו שעשית בשלב הקודם:
posts = Post.query.all()
for post in posts:
print(post.title)
print(post.tags)
print('---')
תקבל פלט דומה לזה:
Output
Post The First
[<Tag "animals">, <Tag "writing">]
---
Post The Third
[<Tag "cooking">, <Tag "tech">, <Tag "writing">]
---
Post The Second
[]
---
A post on life and death
[<Tag "life">, <Tag "death">]
---
A post on joy
[<Tag "joy">]
---
אתה יכול לראות שנוספו פוסטים יחד עם התגיות שלהם.
כדי להדגים איך לשבור קשר בין שני פריטים ביחסי נתונים רבים לרבים, נניח שהפוסט הפוסט השלישי
כבר אינו עוסק בבישול, אז עליכם להסיר את התג בישול
ממנו.
ראשית, עליכם לקבל את הפוסט והתג שברצונכם להסיר:
כאן אתם מביאים את הפוסט בכותרת הפוסט השלישי
באמצעות שיטת filter_by()
. אתם משיגים את התג בישול
. אתם מדפיסים את כותרת הפוסט, את התגים שלו, ואת הפוסטים שתוגנו עם התג בישול
.
שיטת filter_by()
מחזירה אובייקט שאילתה, וניתן להשתמש בשיטת all()
כדי לקבל רשימה של כל התוצאות. אך מכיוון שאנו מצפים לרק תוצאה אחת במקרה זה, אנו משתמשים בשיטת first()
כדי לקבל את התוצאה הראשונה (והיחידה). למידע נוסף על השימוש בשיטות first()
ו- all()
, ראו שלב 4 של כיצד להשתמש ב- Flask-SQLAlchemy כדי לפעול עם מסדי נתונים באפליקציה של Flask.
תקבלו את הפלט הבא:
Output
Post The Third
[<Tag "cooking">, <Tag "tech">, <Tag "writing">]
[<Post "Post The Third">]
כאן אתם רואים את כותרת הפוסט, את התגים של הפוסט, ורשימת הפוסטים שתוגנו עם התג בישול
.
כדי להסיר את התג בישול
מהפוסט, השתמשו בשיטת remove()
כך:
כאן אתם משתמשים בשיטת remove()
כדי לנתק את התג בישול
מהפוסט. לאחר מכן אתם משתמשים בשיטת db.session.commit()
כדי להחיל את השינויים במסד הנתונים.
תקבלו פלט שמאשר שהתג הוסר מהפוסט:
Output[<Tag "tech">, <Tag "writing">]
[]
כפי שאתה רואה, התג cooking
כבר אינו ברשימת התגים של post.tags
, והפוסט הוסר מרשימת הפוסטים של tag.posts
.
צא מהקופסה של Flask:
הוספת פוסטים חדשים ותגי תגיות. תייגת פוסטים והסרת תגיות מפוסטים. בשלב הבא, תציג את התגיות של כל פוסט בדף הבית של הבלוג שלך ב-Flask.
שלב 4 — הצגת תגיות מתחת לכל פוסט
בשלב זה, תערוך את תבנית האינדקס כדי להציג תגיות מתחת לכל פוסט.
ראשית, תסתכל על דף הבית הנוכחי של בלוג ה-Flask.
עם סביבת התכנות שלך מופעלת, תגיד ל-Flask על היישום (app.py
במקרה זה) באמצעות משתנה הסביבה FLASK_APP
. לאחר מכן, הגדר את משתנה הסביבה FLASK_ENV
ל-development
כדי להפעיל את היישום במצב פיתוח:
לבסוף, הרץ את היישום:
עם השרת לפיתוח פועל, בקר בכתובת ה-URL הבאה בדפדפן שלך:
http://127.0.0.1:5000/
תראה עמוד דומה לתמונה הבאה:
השאר את השרת לפיתוח רץ ופתח חלון טרמינל חדש.
תצטרך להציג את התגיות של כל פוסט בשתי עמודים: מתחת לכל פוסט בעמוד האינדקס ומתחת לתוכן הפוסט בעמוד הפוסט. תשתמש באותו קוד כדי להציג את התגיות. כדי למנוע חזרת קוד, תשתמש ב Jinja macro, שמתנהג כמו פונקציה בפייתון. המקרו מחזיק קוד HTML דינמי שניתן להציג בכל מקום שבו תקרא למקרו, ועריכה שלו מיישמת שינויים בכל מקום שבו נקרא. זה מאפשר ניצוליות בקוד.
ראשית, פתח קובץ חדש בשם macros.html
בתיקיית templates
שלך:
הוסף את הקוד הבא לקובץ:
שמור וסגור את הקובץ.
כאן, אתה משתמש במילת המפתח macro
כדי להכריז על מקרו בשם display_tags()
עם פרמטר בשם post
. אתה משתמש בתגית <div>
, שבה אתה מציג כותרת <h4>
. אתה משתמש בלולאת for
כדי לעבור דרך התגיות של אובייקט הפוסט שיעבר כארגומנט למקרו כאשר תקרא לו, דומה לאופן בו ארגומנט מועבר בקריאת פונקציה בפייתון. אתה מקבל תגיות דרך post.tags
. אתה מציג את שם התג בתוך תגית <a>
. תערוך את ערך המאפיין href
כדי ליצור קישור לעמוד תג שתיצור, שבו יוצגו כל הפוסטים המתוייגים בתג מסוים. אתה מציין את סיום המקרו באמצעות מילת המפתח endmacro
.
בשלב הבא, כדי להציג תגיות מתחת לכל פוסט בעמוד האינדקס, פתח את קובץ התבנית index.html
:
ראשית, תצטרך לייבא את המאקרו display_tags()
מהקובץ macros.html
. הוסף את הייבוא הבא בראש הקובץ מעל שורת {% extends 'base.html' %}
:
באמצעות הוספת השורה הבאה בתוך הלולאה for post in posts
, תקרא למאקרו display_tags()
כך:
שמור וסגור את הקובץ.
אתה קורא למאקרו display_tags()
, ומעביר לו את האובייקט post
. זה יציג את שמות התגיות מתחת לכל פוסט.
רענן את עמוד האינדקס בדפדפן שלך ותראה תגיות מתחת לכל פוסט, כפי שמוצג בתמונה הבאה:
בשלב הבא, תוסיף תגיות מתחת לתוכן הפוסט בעמוד הפוסט. פתח את קובץ התבנית post.html
:
ראשית, הוסף את המאקרו display_tags
בראש הקובץ:
לאחר מכן, קרא למאקרו display_tags()
, ומעביר לו את האובייקט post
מתחת לתוכן הפוסט ומעל התגית <hr>
:
<div class="post">
<p><b>#{{ post.id }}</b></p>
<b>
<p class="title">{{ post.title }}</p>
</b>
<div class="content">
<p>{{ post.content }}</p>
</div>
{{ display_tags(post) }}
<hr>
<h3>Comments</h3>
שמור וסגור את הקובץ.
עכשיו, נווט לעמוד פוסט:
http://127.0.0.1:5000/2
תראה שתגיות מוצגות באותו אופן כמו התגיות המוצגות בעמוד האינדקס.
הצגת את התגיות שהוספת לפוסטים מתחת לכל פוסט. בשלב הבא, תוסיף נתיב חדש ליישום ה-Flask שלך שמציג את כל הפוסטים המסומנים בתג מסוים. לאחר מכן, תפעיל את הקישורים של התגים שהצגת בשלב זה.
שלב 5 — הצגת תגיות והפוסטים שלהן
בשלב זה, תוסיף נתיב ותבנית ליישום האינטרנט שלך כדי להציג את התגיות שיש לך במסד הנתונים והפוסטים שלהן.
ראשית, תוסיף נתיב להצגת הפוסטים של כל תג. לדוגמה, הנתיב /tags/שם_התג/
יציג עמוד שמציג את כל הפוסטים שתוגו בתג בשם שם_התג
.
פתח את app.py
לעריכה:
הוסף את הנתיב הבא לסוף הקובץ:
# ...
@app.route('/tags/<tag_name>/')
def tag(tag_name):
tag = Tag.query.filter_by(name=tag_name).first_or_404()
return render_template('tag.html', tag=tag)
שמור וסגור את הקובץ.
בפרק זה אתה משתמש במשתנה URL בשם שם_התג
שמקבע את התג והפוסטים שתוגו בו שיוצגו בעמוד התג. שם התג מועבר לפונקציית התצוגה tag()
דרך הפרמטר שם_התג
, שאתה משתמש בו על השיטה filter_by()
כדי לשאול את התג. אתה משתמש ב־first_or_404()
כדי לקבל את אובייקט התג ולאחסן אותו במשתנה בשם תג
, או להגיב עם הודעת שגיאת 404 Not Found
במקרה שלא קיים תג עם השם הנתון במסד הנתונים.
לאחר מכן, אתה מרנדר קובץ תבנית בשם tag.html
, ומעביר לו את אובייקט התג tag
.
פתח את הקובץ החדש templates/tag.html
לעריכה:
הוסף את הקוד הבא לתוכו:
שמור וסגור את הקובץ.
אתה מייבא את המקרו display_tags()
מהקובץ macros.html
, ומרחיב את תבנית הבסיס.
בתוך בלוק התוכן, אתה מגדיר כותרת ככותרת עם שם התג כלול. לאחר מכן אתה מפעיל לולאה על הפוסטים המתוייגים בתג נתון, שאליה אתה נגיש דרך tag.posts
. אתה מציג את מזהה הפוסט, את כותרת הפוסט ואת תוכן הפוסט. לאחר מכן אתה קורא למקרו display_tags()
כדי להציג את כל התגים של הפוסט.
עם השרת שלך פועל, נווט אל ה-URL הבא:
http://127.0.0.1:5000/tags/writing/
זהו הדף עבור התג writing
. כפי שאתה רואה, כל הפוסטים שתוייגו בתג writing
מוצגים:
עכשיו ערוך את המקרו display_tags()
כדי להפוך את הקישורים של התגים לפועליים. פתח את macros.html
:
ערוך את ערך המאפיין href
כך:
שמור וסגור את הקובץ.
רענן את הדפים בהם המקרו display_tags()
נעשה שימוש, ותראה שהקישורים של התגים פועלים כעת:
http://127.0.0.1:5000/
http://127.0.0.1:5000/2/
http://127.0.0.1:5000/tags/writing/
כפי שאתה רואה, באמצעות מקרו Jinja אפשר לשכפל קוד, ועריכה של מקרו מיישם שינויים במספר תבניות.
הוספת עמוד לתגים יחידים שבו משתמשים יכולים לצפות בכל הפוסטים שתוייגו בתג מסוים, והתגים מתחת לפוסטים מקשרים כעת לעמוד חדש זה.
מסקנה
התכונה שהוספת למערכת הבלוגים שלך מדגימה איך לנהל יחסי רבים לרבים באמצעות הרחבה Flask-SQLAlchemy. למדת כיצד לקשר בין שני טבלאות קשורות באמצעות טבלת שיוך (נקראת גם טבלת שיוך), לקשר ערך עם ערך נוסף, להוסיף את הערך למסד הנתונים, ולגשת ולהפריד מידע מערך.
אם ברצונך לקרוא עוד על Flask, ניתן לבדוק את המדריכים האחרים בסדרת איך לבנות אפליקציות אינטרנט עם Flask.