איך ליצור מודלים ב-Django

הקדמה

בשיעור הקודם, " איך ליצור אפליקציה ב-Django ולחבר אותה למסד נתונים," כיסינו איך ליצור מסד נתונים ב-MySQL, כיצד ליצור ולהתחיל אפליקציה ב-Django, וכיצד לחבר אותה למסד נתונים ב-MySQL.

בשיעור זה, ניצור את המודלים של Django שמגדירים את השדות וההתנהגויות של נתוני האפליקציה "בלוג" שנאחסן. מודלים אלו ממפים את הנתונים מאפליקציה Django שלך למסד הנתונים. זהו מה ש-Django משתמשת בו כדי ליצור את טבלאות המסד נתונים דרך API של התמרת עצמים אובייקטים (ORM), הידוע גם בשם "מודלים".

דרישות מוקדמות

השיעור הזה הוא חלק מסדרת פיתוח Django והוא המשך של סדרה זו.

אם לא עקבת אחרי הסדרה, אנו עושים את ההנחות הבאות:

מכיוון שההדרכה הזו עוסקת בעיקר בדגמים של Django, ייתכן שתוכל לעקוב גם אם יש לך הגדרה מעט שונה.

שלב 1 — צור אפליקציה ב-Django

כדי להיות עקביים עם פילוסופיית ה-Django לגבי המודולריות, ניצור אפליקציה ב-Django בתוך הפרויקט שלנו שתכיל את כל הקבצים הדרושים ליצירת האתר בלוג.

כל פעם שאנו מתחילים לעבוד ב-Python וב-Django, עלינו להפעיל את סביבת הפיתוח שלנו ולהתקדם לתיקייה הראשית של האפליקציה. אם עקבת אחרי הסדרה, תוכל להשיג זאת על ידי הקלדת הפקודה הבאה.

  1. cd ~/my_blog_app
  2. . env/bin/activate
  3. cd blog

משם נריץ את הפקודה הבאה:

  1. python manage.py startapp blogsite

הדרך ליצירת האפליקציה שלנו כוללת יצירת תיקייה בשם blogsite.

בנקודה זו בסדרת התרגול, יש לך את מבנה התיקיות הבא עבור הפרויקט שלך:

my_blog_app/
└── blog
    ├── blog
    │   ├── __init__.py
    │   ├── __pycache__
    │   │   ├── __init__.cpython-38.pyc
    │   │   ├── settings.cpython-38.pyc
    │   │   ├── urls.cpython-38.pyc
    │   │   └── wsgi.cpython-38.pyc
    │   ├── asgi.py
    │   ├── settings.py
    │   ├── urls.py
    │   └── wsgi.py
    ├── blogsite
    │   ├── __init__.py
    │   ├── admin.py
    │   ├── apps.py
    │   ├── migrations
    │   │   └── __init__.py
    │   ├── models.py
    │   ├── tests.py
    │   └── views.py
    └── manage.py

הקובץ שנתמקד בו בקורס זה הוא קובץ models.py, הנמצא בתיקייה blogsite.

שלב 2 — הוסף את מודל הפוסט

יש צורך ראשית לפתוח ולערוך את קובץ models.py כך שיכיל את הקוד ליצירת מודל Post. מודל Post יכיל את השדות הבאים בבסיס הנתונים:

  • title — כותרת הפוסט בבלוג.
  • slug — מקום שבו יישמרו ויפורטו כתובות URL תקפות לעמודי האינטרנט.
  • content — התוכן הטקסטואלי של הפוסט בבלוג.
  • created_on — התאריך בו נוצר הפוסט.
  • author — הכותב של הפוסט.

עכשיו, נכנס לתיקייה בה נמצא קובץ models.py.

  1. cd ~/my_blog_app/blog/blogsite

נשתמש בפקודת cat כדי להציג את תוכן הקובץ בטרמינל.

  1. cat models.py

הקובץ צריך להכיל את הקוד הבא, המייבא מודלים, יחד עם הערה שמתארת מה יש למקם בקובץ models.py זה.

models.py
from django.db import models

# יצירת המודלים שלך כאן.

השתמשו בעורך הטקסט המועדף עליכם כדי להוסיף את הקוד הבא לקובץ models.py. אנו נשתמש ב־nano כעורך הטקסט שלנו, אך אתם מוזמנים להשתמש במה שתעדיפו.

  1. nano models.py

בתוך קובץ זה, קוד לייבוא של API המודלים כבר נוסף, ואפשר למחוק את ההערה שבמשך. לאחר מכן נייבא את slugify כדי ליצור slugs ממחרוזות, את User של Django למערכת האימות, ואת reverse מ־django.urls כדי לספק לנו גמישות רבה יותר ביצירת כתובות URL.

models.py
from django.db import models
from django.template.defaultfilters import slugify
from django.contrib.auth.models import User
from django.urls import reverse

לאחר מכן, נוסיף את השיטה המחלקתית למחלקת המודל שנקראת Post, עם שדות מסד נתונים הבאים: title, slug, content, created_on ו־author. נוסיף אותם מתחת להצהרות הייבוא.

models.py
...
class Post(models.Model):
    title = models.CharField(max_length=255)
    slug = models.SlugField(unique=True, max_length=255)
    content = models.TextField()
    created_on = models.DateTimeField(auto_now_add=True)
    author = models.TextField()

לבסוף, נוסיף את הדגשת הפונקציונליות ליצירת הכתובת URL והפונקציה לשמירת הפוסט. זה חיוני, מכיוון שזה יוצר קישור ייחודי להתאמת הפוסט הייחודי שלנו.

models.py
...
    def get_absolute_url(self):
        return reverse('blog_post_detail', args=[self.slug])

    def save(self, *args, **kwargs):
        if not self.slug:
            self.slug = slugify(self.title)
        super(Post, self).save(*args, **kwargs)

עכשיו, עלינו לספר למודל כיצד הפוסטים ייסדרו ויתצגו בדף האינטרנט. הלוגיקה לכך תתווסף למחלקת Meta פנימית מקוננת. מחלקת ה־Meta בדרך כלל מכילה לוגיקה רבה של מודל שאינה קשורה להגדרת שדות מסד הנתונים.

models.py
...
    class Meta:
        ordering = ['created_on']

        def __unicode__(self):
            return self.title

לבסוף, נוסיף את מודל התגובות (Comment) לקובץ זה. זה כולל הוספת מחלקה נוספת בשם Comment עם models.Models בחתימתו והשדות מסד נתונים הבאים מוגדרים:

  • name — שם האדם שמפרסם את התגובה.
  • דואר אלקטרוני – כתובת הדואר האלקטרוני של האדם שמפרסם את התגובה.
  • טקסט – הטקסט של התגובה עצמה.
  • פוסט – הפוסט שבו נעשתה התגובה.
  • נוצר ב – הזמן בו נוצרה התגובה.
models.py
...
class Comment(models.Model):
    name = models.CharField(max_length=42)
    email = models.EmailField(max_length=75)
    website = models.URLField(max_length=200, null=True, blank=True)
    content = models.TextField()
    post = models.ForeignKey(Post, on_delete=models.CASCADE)
    created_on = models.DateTimeField(auto_now_add=True)

בנקודה זו models.py תהיה מושלמת. ודא שקובץ ה-models.py שלך תואם את המפורט למטה:

models.py
from django.db import models
from django.template.defaultfilters import slugify
from django.contrib.auth.models import User
from django.urls import reverse


class Post(models.Model):
    title = models.CharField(max_length=255)
    slug = models.SlugField(unique=True, max_length=255)
    content = models.TextField()
    created_on = models.DateTimeField(auto_now_add=True)
    author = models.TextField()

    def get_absolute_url(self):
        return reverse('blog_post_detail', args=[self.slug])
    
    def save(self, *args, **kwargs):
        if not self.slug:
            self.slug = slugify(self.title)
        super(Post, self).save(*args, **kwargs)

    class Meta:
        ordering = ['created_on']

        def __unicode__(self):
            return self.title


class Comment(models.Model):
    name = models.CharField(max_length=42)
    email = models.EmailField(max_length=75)
    website = models.URLField(max_length=200, null=True, blank=True)
    content = models.TextField()
    post = models.ForeignKey(Post, on_delete=models.CASCADE)
    created_on = models.DateTimeField(auto_now_add=True)


ודא ששמרת וסגרת את הקובץ. אם אתה משתמש בננו, תוכל לעשות זאת על ידי הקלדת CTRL ואז X, אז Y, אז ENTER.

עם קובץ ה-models.py מוגדר, אנו יכולים להמשיך ולעדכן את קובץ ה-settings.py שלנו.

שלב 3 — עדכון ההגדרות

כעת שהוספנו מודלים לאפליקציה שלנו, עלינו ליידע את הפרויקט שלנו על קיום האפליקציה blogsite שהוספנו לאחרונה. אנו עושים זאת על ידי הוספתה לסעיף INSTALLED_APPS בתוך settings.py.

נווט לתיקייה בה קובץ ה-settings.py שלך ממוקם.

  1. cd ~/my_blog_app/blog/blog

מכאן, פתח את קובץ ה-settings.py שלך, לדוגמה באמצעות ננו.

  1. nano settings.py

עם הקובץ פתוח, הוסף את האפליקציה שלך blogsite לסעיף INSTALLED_APPS שבקובץ, כפי שמצויין למטה.

settings.py
# הגדרת האפליקציות
INSTALLED_APPS = [
    'blogsite',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

עם האפליקציה blogsite שנוספה, אתה יכול לשמור ולצאת מהקובץ.

בנקודה זו, אנחנו מוכנים להמשיך וליישם את השינויים הללו.

שלב 4 – לבצע העברות

עם המודלים שלנו Post ו־Comment נוספו, השלב הבא הוא ליישם את השינויים כך שסכימת מסד הנתונים שלנו MySQL תזהה אותם ותיצור את הטבלאות הנדרשות.

ראשית, עלינו לארוז את השינויים במודל שלנו לקבצי העברה יחידים באמצעות הפקודה makemigrations. קבצים אלו דומים לאלו של commits במערכת בקרת גרסאות כמו Git.

כעת, אם תנוודו אל ~/my_blog_app/blog/blogsite/migrations ותפעילו את ls, תשימו לב שיש רק קובץ __init__.py. זה ישתנה כאשר נוסיף את ההעברות.

שנה את התיקייה לתיקיית הבלוג באמצעות cd, כך:

  1. cd ~/my_blog_app/blog

ואז הפעילו את הפקודה makemigrations על manage.py.

  1. python manage.py makemigrations

תקבל את הפלט הבא בחלון הטרמינל שלך:

Output
Migrations for 'blogsite': blogsite/migrations/0001_initial.py - Create model Post - Create model Comment

זכור, כאשר נווטנו אל /~/my_blog_app/blog/blogsite/migrations ורק קיים הקובץ __init__.py? אם נחזור כעת לתיקייה הזו נגלה שנוספו שני פריטים: __pycache__ ו־0001_initial.py. הקובץ 0001_initial.py נוצר באופן אוטומטי כאשר הרצת את הפקודה makemigrations. קובץ דומה ייווצר בכל פעם שתריץ makemigrations.

הרץ less 0001_initial.py מהתיקייה בה הוא נמצא אם ברצונך לקרוא מה יש בקובץ.

כעת נווט אל ~/my_blog_app/blog:

  1. cd ~/my_blog_app/blog

מכיוון שיש לנו קובץ המיגרציה, עלינו להחיל את השינויים שהם מתארים לבסיס הנתונים באמצעות הפקודה migrate. אך קודם נבדוק אילו מיגרציות קיימות כרגע, באמצעות הפקודה showmigrations.

  1. python manage.py showmigrations
Output
admin [X] 0001_initial [X] 0002_logentry_remove_auto_add [X] 0003_logentry_add_action_flag_choices auth [X] 0001_initial [X] 0002_alter_permission_name_max_length [X] 0003_alter_user_email_max_length [X] 0004_alter_user_username_opts [X] 0005_alter_user_last_login_null [X] 0006_require_contenttypes_0002 [X] 0007_alter_validators_add_error_messages [X] 0008_alter_user_username_max_length [X] 0009_alter_user_last_name_max_length [X] 0010_alter_group_name_max_length [X] 0011_update_proxy_permissions blogsite [ ] 0001_initial contenttypes [X] 0001_initial [X] 0002_remove_content_type_name sessions [X] 0001_initial

תגלה כי כל המיגרציות סומנו חוץ מאלה של 0001_initial שיצרנו עם המודלים Post ו־Comment.

כעת נבדוק אילו פקודות SQL יושגו בעת ביצוע המיגרציות, באמצעות הפקודה הבאה. היא מקבלת את המיגרציה ואת כותרת המיגרציה כארגומנט:

  1. python manage.py sqlmigrate blogsite 0001_initial

מטה מוצגת השאילתת SQL האמיתית שנעשית מאחורי הקלעים.

Output
-- -- יצירת מודל Post -- CREATE TABLE `blogsite_post` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `title` varchar(255) NOT NULL, `slug` varchar(255) NOT NULL UNIQUE, `content` longtext NOT NULL, `created_on` datetime(6) NOT NULL, `author` longtext NOT NULL); -- -- יצירת מודל Comment -- CREATE TABLE `blogsite_comment` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `name` varchar(42) NOT NULL, `email` varchar(75) NOT NULL, `website` varchar(200) NULL, `content` longtext NOT NULL, `created_on` datetime(6) NOT NULL, `post_id` integer NOT NULL); ALTER TABLE `blogsite_comment` ADD CONSTRAINT `blogsite_comment_post_id_de248bfe_fk_blogsite_post_id` FOREIGN KEY (`post_id`) REFERENCES `blogsite_post` (`id`);

כעת נבצע את המיגרציות כך שיחולקו לבסיס הנתונים שלנו שב־MySQL.

  1. python manage.py migrate

נקבל את הפלט הבא:

Output
Operations to perform: Apply all migrations: admin, auth, blogsite, contenttypes, sessions Running migrations: Applying blogsite.0001_initial... OK

כעת הגעת להפעיל את המעברים שלך בהצלחה.

חשוב לזכור כי יש שלוש נקודות לשימור בדקת המעברים של Django עם MySQL כבסיס הנתונים שלך, כפי שמצוין במסמך הטכני של Django.

  • חוסר תמיכה בעסקאות שמסביב לפעולות שינוי בסכימה. במילים אחרות, אם המעבר נכשל בהצלחה, יהיה עליך לבטל ידנית את השינויים שביצעת כדי לנסות מעבר נוסף. אין אפשרות לגלול לנקודה קודמת, לפני שנעשו שינויים במעבר הנכשל.
  • לרוב הפעולות של שינוי בסכימה, MySQL יכתוב מחדש תצורת טבלאות. במקרה הגרוע, יחס הזמן יהיה פרופורציונלי למספר השורות בטבלה להוספת או הסרת עמודות. על פי תיעוד Django, זה יכול להיות כה איטי כדקה למיליון שורות.
  • ב-MySQL יש הגבלות קטנות על אורכי שמות לעמודות, טבלאות ואינדקסים. יש גם הגבלה על גודל המשולב של כל העמודות והכיסוי של האינדקסים. בעוד שמספר מסדי נתונים אחרים יכולים לתמוך בהגבלות גבוהות שנוצרו ב-Django, אינדקסים אלו יכשלו להיות נוצרים עם MySQL כבסיס נתונים במקום.

לכל מסד נתונים שתשקול לשימוש עם Django, חשוב לשקול את היתרונות והחסרונות של כל אחד.

שלב 5 — אמת את סכימת המסד נתונים

עם המעברים השלמים, עלינו לוודא את הייצוב המוצלח של הטבלאות של MySQL שיצרנו דרך מודלי Django שלנו.

כדי לעשות זאת, הריצו את הפקודה הבאה בטרמינל כדי להתחבר ל-MySQL. נשתמש ב־djangouser שיצרנו ב־מדריך הקודם.

  1. mysql blog_data -u djangouser

כעת, בחרו את מסד הנתונים שלנו blog_data. אם אינכם יודעים איזה מסד נתונים אתם משתמשים בו, תוכלו להציג את כל המסדים עם SHOW DATABASES; ב-SQL.

  1. USE blog_data;

אז הקלידו את הפקודה הבאה כדי להציג את הטבלאות.

  1. SHOW TABLES;

בקשת ה-SQL הזו אמורה לחשוף את הבאים:

Output
+----------------------------+ | Tables_in_blog_data | +----------------------------+ | auth_group | | auth_group_permissions | | auth_permission | | auth_user | | auth_user_groups | | auth_user_user_permissions | | blogsite_comment | | blogsite_post | | django_admin_log | | django_content_type | | django_migrations | | django_session | +----------------------------+ 12 rows in set (0.01 sec)

בין הטבלאות יש blogsite_comment ו־blogsite_post. אלה הם המודלים שיצרנו לפני זמן קצר. בואו נוודא שהם מכילים את השדות שהגדרנו.

  1. DESCRIBE blogsite_comment;
Output
+------------+--------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +------------+--------------+------+-----+---------+----------------+ | id | int | NO | PRI | NULL | auto_increment | | name | varchar(42) | NO | | NULL | | | email | varchar(75) | NO | | NULL | | | website | varchar(200) | YES | | NULL | | | content | longtext | NO | | NULL | | | created_on | datetime(6) | NO | | NULL | | | post_id | int | NO | MUL | NULL | | +------------+--------------+------+-----+---------+----------------+ 7 rows in set (0.00 sec)
  1. DESCRIBE blogsite_post;
Output
+------------+--------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +------------+--------------+------+-----+---------+----------------+ | id | int | NO | PRI | NULL | auto_increment | | title | varchar(255) | NO | | NULL | | | slug | varchar(255) | NO | UNI | NULL | | | content | longtext | NO | | NULL | | | created_on | datetime(6) | NO | | NULL | | | author | longtext | NO | | NULL | | +------------+--------------+------+-----+---------+----------------+ 6 rows in set (0.00 sec)

אמרנו ווידאנו שטבלאות מסד הנתונים נוצרו בהצלחה מהמחזורים של מודל ה-Django שלנו.

ניתן לסגור את MySQL עם CTRL + D וכאשר תרצו לצאת מהסביבה של פייתון, תוכלו להריץ את הפקודה deactivate:

  1. deactivate

השבתת הסביבת התכנות שלכם תחזיר אתכם לציוד הפקודה בטרמינל.

מסקנה

במדריך זה, הוספנו בהצלחה מודלים עבור פונקציונליות בסיסית ביישום אינטרנטי של בלוג. למדת כיצד לכתוב מודלים, כיצד עובדות המיגרציות, והתהליך של תרגום מודלי Django לטבלאות בסיס נתונים ב MySQL.

Source:
https://www.digitalocean.com/community/tutorials/how-to-create-django-models