كيفية إنشاء نماذج Django

مقدمة

في البرنامج التعليمي السابق، “كيفية إنشاء تطبيق Django وربطه بقاعدة بيانات”، قمنا بشرح كيفية إنشاء قاعدة بيانات MySQL، وكيفية إنشاء وبدء تطبيق Django، وكيفية ربطه بقاعدة بيانات MySQL.

في هذا البرنامج التعليمي، سنقوم بإنشاء نماذج Django التي تحدد الحقول والسلوكيات لبيانات تطبيق Blog التي سنقوم بتخزينها. تُعيد هذه النماذج بيانات تطبيق Django إلى قاعدة البيانات. إنها الطريقة التي يستخدمها Django لإنشاء جداول قاعدة البيانات من خلال واجهة برمجة التطبيقات الخاصة بهم للتعامل مع البيانات، والتي تُشار إليها بـ “النماذج”.

المتطلبات المسبقة

يعتبر هذا البرنامج التعليمي جزءًا من سلسلة تطوير Django وهو استمرار لتلك السلسلة.

إذا لم تتبع هذه السلسلة، فيُفترض أن:

  • لديك إصدار Django 4 أو أعلى مثبتًا.
  • لقد قمتَ بربط تطبيق Django الخاص بك بقاعدة بيانات. نحن نستخدم MySQL، ويمكنك تحقيق هذا الاتصال من خلال متابعة الجزء الثاني من سلسلة Django، “كيفية إنشاء تطبيق Django وربطه بقاعدة بيانات“.
  • أنت تعمل على نظام تشغيل قائم على Unix، ويفضل أن يكون خادم سحابي Ubuntu 22.04 هو النظام الذي قمنا باختباره عليه. إذا كنت ترغب في إعداد Django في بيئة مماثلة، يرجى الرجوع إلى دورتنا التعليمية “كيفية تثبيت Django وإعداد بيئة تطوير على Ubuntu 22.04“.

نظرًا لأن هذا البرنامج التعليمي يتعامل بشكل رئيسي مع نماذج Django، قد تكون قادرًا على متابعته حتى إذا كان لديك إعداد مختلف إلى حد ما.

الخطوة 1 — إنشاء تطبيق Django

لنكون متسقين مع فلسفة Django الخاصة بالتجزئة، سنقوم بإنشاء تطبيق Django داخل مشروعنا يحتوي على جميع الملفات اللازمة لإنشاء موقع الويب للمدونة.

كلما بدأنا في العمل في Python و Django، يجب علينا تنشيط بيئة Python الافتراضية الخاصة بنا والانتقال إلى دليل تطبيقنا الجذر. إذا كنت قد تبعت السلسلة، يمكنك تحقيق ذلك عن طريق كتابة الأمر التالي.

  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.

الخطوة ٢ — إضافة نموذج المشاركات

أولاً، نحتاج إلى فتح وتحرير ملف 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

في هذا الملف، تم بالفعل إضافة الكود لاستيراد واجهة برمجة التطبيقات للنماذج، يمكننا المضي قدمًا وحذف التعليق الذي يليه. ثم سنقوم بإضافة استيراد لـ `slugify` لإنشاء شرائط للنصوص، و `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. هذه الملفات مشابهة لتلك التي في نظام التحكم في الإصدارات مثل 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؟ إذا تم cd العودة إلى ذلك الدليل الآن سنلاحظ أنه تمت إضافة عنصرين: __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 وعندما تكون جاهزًا لمغادرة بيئة Python الخاصة بك ، يمكنك تشغيل الأمر deactivate:

  1. deactivate

تعطيل بيئة البرمجة الخاصة بك سيعيدك إلى موجه الأوامر في الطرفية.

الاستنتاج

في هذا البرنامج التعليمي، قمنا بنجاح بإضافة النماذج للوظائف الأساسية في تطبيق ويب للمدونة. لقد تعلمت كيفية كتابة النماذج، وكيفية عمل الترحيلات وعملية ترجمة نماذج Django إلى الجداول الفعلية في قاعدة البيانات MySQL الفعلية.

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